@aztec/end-to-end 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2 → 0.77.0-testnet-ignition.21

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 (138) hide show
  1. package/README.md +2 -0
  2. package/dest/bench/utils.d.ts +70 -0
  3. package/dest/bench/utils.d.ts.map +1 -0
  4. package/dest/bench/utils.js +24 -8
  5. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +46 -0
  6. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -0
  7. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +17 -17
  8. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +47 -0
  9. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -0
  10. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +27 -16
  11. package/dest/e2e_deploy_contract/deploy_test.d.ts +28 -0
  12. package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -0
  13. package/dest/e2e_deploy_contract/deploy_test.js +4 -7
  14. package/dest/e2e_epochs/epochs_test.d.ts +51 -0
  15. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -0
  16. package/dest/e2e_epochs/epochs_test.js +155 -0
  17. package/dest/e2e_fees/fees_test.d.ts +73 -0
  18. package/dest/e2e_fees/fees_test.d.ts.map +1 -0
  19. package/dest/e2e_fees/fees_test.js +75 -32
  20. package/dest/e2e_nested_contract/nested_contract_test.d.ts +26 -0
  21. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -0
  22. package/dest/e2e_nested_contract/nested_contract_test.js +14 -12
  23. package/dest/e2e_p2p/p2p_network.d.ts +61 -0
  24. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -0
  25. package/dest/e2e_p2p/p2p_network.js +54 -30
  26. package/dest/e2e_p2p/shared.d.ts +10 -0
  27. package/dest/e2e_p2p/shared.d.ts.map +1 -0
  28. package/dest/e2e_p2p/shared.js +7 -8
  29. package/dest/e2e_prover/e2e_prover_test.d.ts +56 -0
  30. package/dest/e2e_prover/e2e_prover_test.d.ts.map +1 -0
  31. package/dest/e2e_prover/e2e_prover_test.js +20 -24
  32. package/dest/e2e_token_contract/token_contract_test.d.ts +29 -0
  33. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -0
  34. package/dest/e2e_token_contract/token_contract_test.js +4 -7
  35. package/dest/fixtures/fixtures.d.ts +17 -0
  36. package/dest/fixtures/fixtures.d.ts.map +1 -0
  37. package/dest/fixtures/fixtures.js +2 -2
  38. package/dest/fixtures/get_acvm_config.d.ts +8 -0
  39. package/dest/fixtures/get_acvm_config.d.ts.map +1 -0
  40. package/dest/fixtures/get_acvm_config.js +10 -5
  41. package/dest/fixtures/get_bb_config.d.ts +6 -0
  42. package/dest/fixtures/get_bb_config.d.ts.map +1 -0
  43. package/dest/fixtures/get_bb_config.js +9 -4
  44. package/dest/fixtures/index.d.ts +6 -0
  45. package/dest/fixtures/index.d.ts.map +1 -0
  46. package/dest/fixtures/l1_to_l2_messaging.d.ts +13 -0
  47. package/dest/fixtures/l1_to_l2_messaging.d.ts.map +1 -0
  48. package/dest/fixtures/l1_to_l2_messaging.js +1 -1
  49. package/dest/fixtures/logging.d.ts +8 -0
  50. package/dest/fixtures/logging.d.ts.map +1 -0
  51. package/dest/fixtures/setup_l1_contracts.d.ts +6 -0
  52. package/dest/fixtures/setup_l1_contracts.d.ts.map +1 -0
  53. package/dest/fixtures/setup_l1_contracts.js +6 -4
  54. package/dest/fixtures/setup_p2p_test.d.ts +22 -0
  55. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -0
  56. package/dest/fixtures/setup_p2p_test.js +5 -3
  57. package/dest/fixtures/snapshot_manager.d.ts +87 -0
  58. package/dest/fixtures/snapshot_manager.d.ts.map +1 -0
  59. package/dest/fixtures/snapshot_manager.js +67 -74
  60. package/dest/fixtures/token_utils.d.ts +6 -0
  61. package/dest/fixtures/token_utils.d.ts.map +1 -0
  62. package/dest/fixtures/token_utils.js +1 -1
  63. package/dest/fixtures/utils.d.ts +155 -0
  64. package/dest/fixtures/utils.d.ts.map +1 -0
  65. package/dest/fixtures/utils.js +97 -71
  66. package/dest/fixtures/with_telemetry_utils.d.ts +3 -0
  67. package/dest/fixtures/with_telemetry_utils.d.ts.map +1 -0
  68. package/dest/index.d.ts +2 -0
  69. package/dest/index.d.ts.map +1 -0
  70. package/dest/quality_of_service/alert_checker.d.ts +41 -0
  71. package/dest/quality_of_service/alert_checker.d.ts.map +1 -0
  72. package/dest/quality_of_service/alert_checker.js +4 -1
  73. package/dest/sample-dapp/index.js +1 -1
  74. package/dest/shared/cross_chain_test_harness.d.ts +124 -0
  75. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -0
  76. package/dest/shared/cross_chain_test_harness.js +6 -17
  77. package/dest/shared/gas_portal_test_harness.d.ts +80 -0
  78. package/dest/shared/gas_portal_test_harness.d.ts.map +1 -0
  79. package/dest/shared/gas_portal_test_harness.js +11 -4
  80. package/dest/shared/index.d.ts +2 -0
  81. package/dest/shared/index.d.ts.map +1 -0
  82. package/dest/shared/index.js +0 -1
  83. package/dest/shared/jest_setup.d.ts +2 -0
  84. package/dest/shared/jest_setup.d.ts.map +1 -0
  85. package/dest/shared/submit-transactions.d.ts +4 -0
  86. package/dest/shared/submit-transactions.d.ts.map +1 -0
  87. package/dest/shared/submit-transactions.js +9 -17
  88. package/dest/shared/uniswap_l1_l2.d.ts +25 -0
  89. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -0
  90. package/dest/shared/uniswap_l1_l2.js +5 -10
  91. package/dest/simulators/index.d.ts +3 -0
  92. package/dest/simulators/index.d.ts.map +1 -0
  93. package/dest/simulators/lending_simulator.d.ts +69 -0
  94. package/dest/simulators/lending_simulator.d.ts.map +1 -0
  95. package/dest/simulators/lending_simulator.js +1 -3
  96. package/dest/simulators/token_simulator.d.ts +29 -0
  97. package/dest/simulators/token_simulator.d.ts.map +1 -0
  98. package/dest/spartan/setup_test_wallets.d.ts +20 -0
  99. package/dest/spartan/setup_test_wallets.d.ts.map +1 -0
  100. package/dest/spartan/setup_test_wallets.js +72 -38
  101. package/dest/spartan/utils.d.ts +415 -0
  102. package/dest/spartan/utils.d.ts.map +1 -0
  103. package/dest/spartan/utils.js +169 -43
  104. package/package.json +35 -40
  105. package/src/bench/utils.ts +30 -13
  106. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +40 -30
  107. package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +34 -18
  108. package/src/e2e_deploy_contract/deploy_test.ts +6 -11
  109. package/src/e2e_epochs/epochs_test.ts +217 -0
  110. package/src/e2e_fees/fees_test.ts +84 -38
  111. package/src/e2e_nested_contract/nested_contract_test.ts +14 -16
  112. package/src/e2e_p2p/p2p_network.ts +67 -47
  113. package/src/e2e_p2p/shared.ts +16 -10
  114. package/src/e2e_prover/e2e_prover_test.ts +56 -37
  115. package/src/e2e_token_contract/token_contract_test.ts +10 -11
  116. package/src/fixtures/fixtures.ts +2 -2
  117. package/src/fixtures/get_acvm_config.ts +7 -3
  118. package/src/fixtures/get_bb_config.ts +6 -2
  119. package/src/fixtures/l1_to_l2_messaging.ts +6 -13
  120. package/src/fixtures/setup_l1_contracts.ts +8 -7
  121. package/src/fixtures/setup_p2p_test.ts +8 -6
  122. package/src/fixtures/snapshot_manager.ts +72 -79
  123. package/src/fixtures/token_utils.ts +2 -2
  124. package/src/fixtures/utils.ts +135 -97
  125. package/src/guides/up_quick_start.sh +10 -5
  126. package/src/quality_of_service/alert_checker.ts +6 -2
  127. package/src/sample-dapp/index.mjs +1 -1
  128. package/src/shared/cross_chain_test_harness.ts +17 -35
  129. package/src/shared/gas_portal_test_harness.ts +21 -11
  130. package/src/shared/index.ts +0 -1
  131. package/src/shared/submit-transactions.ts +16 -20
  132. package/src/shared/uniswap_l1_l2.ts +35 -26
  133. package/src/simulators/lending_simulator.ts +5 -6
  134. package/src/simulators/token_simulator.ts +1 -1
  135. package/src/spartan/setup_test_wallets.ts +111 -37
  136. package/src/spartan/utils.ts +161 -54
  137. package/dest/shared/browser.js +0 -163
  138. package/src/shared/browser.ts +0 -272
@@ -1,28 +1,29 @@
1
- import { getSchnorrAccount } from '@aztec/accounts/schnorr';
2
- import { type AztecNodeConfig } from '@aztec/aztec-node';
1
+ import { getSchnorrWallet } from '@aztec/accounts/schnorr';
2
+ import type { AztecNodeConfig } from '@aztec/aztec-node';
3
3
  import {
4
4
  type AccountWallet,
5
5
  AztecAddress,
6
6
  type AztecNode,
7
+ CheatCodes,
7
8
  type CompleteAddress,
8
9
  EthAddress,
9
10
  type Logger,
10
11
  type PXE,
11
12
  createLogger,
12
13
  } from '@aztec/aztec.js';
13
- import { createL1Clients } from '@aztec/ethereum';
14
- import { InboxAbi, OutboxAbi, RollupAbi } from '@aztec/l1-artifacts';
14
+ import { type ViemPublicClient, createL1Clients, deployL1Contract } from '@aztec/ethereum';
15
+ import { InboxAbi, OutboxAbi, RollupAbi, TestERC20Abi, TestERC20Bytecode } from '@aztec/l1-artifacts';
15
16
  import { TokenContract } from '@aztec/noir-contracts.js/Token';
16
17
  import { TokenBridgeContract } from '@aztec/noir-contracts.js/TokenBridge';
17
18
 
18
- import { type Chain, type HttpTransport, type PublicClient, getContract } from 'viem';
19
+ import { getContract } from 'viem';
19
20
 
20
21
  import { MNEMONIC } from '../fixtures/fixtures.js';
21
22
  import {
22
23
  type ISnapshotManager,
23
24
  type SubsystemsContext,
24
- addAccounts,
25
25
  createSnapshotManager,
26
+ deployAccounts,
26
27
  publicDeployAccounts,
27
28
  } from '../fixtures/snapshot_manager.js';
28
29
  import { CrossChainTestHarness } from '../shared/cross_chain_test_harness.js';
@@ -38,7 +39,7 @@ export class CrossChainMessagingTest {
38
39
  pxe!: PXE;
39
40
  aztecNodeConfig!: AztecNodeConfig;
40
41
 
41
- publicClient!: PublicClient<HttpTransport, Chain> | undefined;
42
+ publicClient!: ViemPublicClient | undefined;
42
43
 
43
44
  user1Wallet!: AccountWallet;
44
45
  user2Wallet!: AccountWallet;
@@ -51,6 +52,7 @@ export class CrossChainMessagingTest {
51
52
  rollup!: any; // GetContractReturnType<typeof RollupAbi> | undefined;
52
53
  inbox!: any; // GetContractReturnType<typeof InboxAbi> | undefined;
53
54
  outbox!: any; // GetContractReturnType<typeof OutboxAbi> | undefined;
55
+ cheatcodes!: CheatCodes;
54
56
 
55
57
  constructor(testName: string) {
56
58
  this.logger = createLogger(`e2e:e2e_cross_chain_messaging:${testName}`);
@@ -58,7 +60,7 @@ export class CrossChainMessagingTest {
58
60
  }
59
61
 
60
62
  async assumeProven() {
61
- await this.rollup.write.setAssumeProvenThroughBlockNumber([await this.rollup.read.getPendingBlockNumber()]);
63
+ await this.cheatcodes.rollup.markAsProven(await this.rollup.read.getPendingBlockNumber());
62
64
  }
63
65
 
64
66
  async setup() {
@@ -66,6 +68,7 @@ export class CrossChainMessagingTest {
66
68
  this.aztecNode = aztecNode;
67
69
  this.pxe = pxe;
68
70
  this.aztecNodeConfig = aztecNodeConfig;
71
+ this.cheatcodes = await CheatCodes.create(this.aztecNodeConfig.l1RpcUrls, this.pxe);
69
72
  }
70
73
 
71
74
  snapshot = <T>(
@@ -84,14 +87,9 @@ export class CrossChainMessagingTest {
84
87
 
85
88
  await this.snapshotManager.snapshot(
86
89
  '3_accounts',
87
- addAccounts(3, this.logger),
88
- async ({ accountKeys }, { pxe, aztecNodeConfig, aztecNode, deployL1ContractsValues }) => {
89
- this.wallets = await Promise.all(
90
- accountKeys.map(async ak => {
91
- const account = await getSchnorrAccount(pxe, ak[0], ak[1], 1);
92
- return account.getWallet();
93
- }),
94
- );
90
+ deployAccounts(3, this.logger),
91
+ async ({ deployedAccounts }, { pxe, aztecNodeConfig, aztecNode, deployL1ContractsValues }) => {
92
+ this.wallets = await Promise.all(deployedAccounts.map(a => getSchnorrWallet(pxe, a.address, a.signingKey)));
95
93
  this.accounts = this.wallets.map(w => w.getCompleteAddress());
96
94
  this.wallets.forEach((w, i) => this.logger.verbose(`Wallet ${i} address: ${w.getAddress()}`));
97
95
 
@@ -118,7 +116,24 @@ export class CrossChainMessagingTest {
118
116
  this.logger.verbose(`Public deploy accounts...`);
119
117
  await publicDeployAccounts(this.wallets[0], this.accounts.slice(0, 3));
120
118
 
121
- const { publicClient, walletClient } = createL1Clients(this.aztecNodeConfig.l1RpcUrl, MNEMONIC);
119
+ const { publicClient, walletClient } = createL1Clients(this.aztecNodeConfig.l1RpcUrls, MNEMONIC);
120
+
121
+ const underlyingERC20Address = await deployL1Contract(
122
+ walletClient,
123
+ publicClient,
124
+ TestERC20Abi,
125
+ TestERC20Bytecode,
126
+ ['Underlying', 'UND', walletClient.account.address],
127
+ ).then(({ address }) => address);
128
+
129
+ const underlyingERC20 = getContract({
130
+ address: underlyingERC20Address!.toString(),
131
+ abi: TestERC20Abi,
132
+ client: walletClient,
133
+ });
134
+
135
+ // allow anyone to mint
136
+ await underlyingERC20.write.setFreeForAll([true], {} as any);
122
137
 
123
138
  this.logger.verbose(`Setting up cross chain harness...`);
124
139
  this.crossChainTestHarness = await CrossChainTestHarness.new(
@@ -128,6 +143,7 @@ export class CrossChainMessagingTest {
128
143
  walletClient,
129
144
  this.wallets[0],
130
145
  this.logger,
146
+ underlyingERC20Address,
131
147
  );
132
148
 
133
149
  this.logger.verbose(`L2 token deployed to: ${this.crossChainTestHarness.l2Token.address}`);
@@ -143,7 +159,7 @@ export class CrossChainMessagingTest {
143
159
  this.ownerAddress = AztecAddress.fromString(crossChainContext.ownerAddress.toString());
144
160
  const tokenPortalAddress = EthAddress.fromString(crossChainContext.tokenPortal.toString());
145
161
 
146
- const { publicClient, walletClient } = createL1Clients(this.aztecNodeConfig.l1RpcUrl, MNEMONIC);
162
+ const { publicClient, walletClient } = createL1Clients(this.aztecNodeConfig.l1RpcUrls, MNEMONIC);
147
163
 
148
164
  const inbox = getContract({
149
165
  address: this.aztecNodeConfig.l1Contracts.inboxAddress.toString(),
@@ -1,4 +1,4 @@
1
- import { getSchnorrAccount } from '@aztec/accounts/schnorr';
1
+ import { getSchnorrWallet } from '@aztec/accounts/schnorr';
2
2
  import {
3
3
  type AccountWallet,
4
4
  type AztecAddress,
@@ -13,9 +13,9 @@ import {
13
13
  createLogger,
14
14
  getContractInstanceFromDeployParams,
15
15
  } from '@aztec/aztec.js';
16
- import { type StatefulTestContract } from '@aztec/noir-contracts.js/StatefulTest';
16
+ import type { StatefulTestContract } from '@aztec/noir-contracts.js/StatefulTest';
17
17
 
18
- import { type ISnapshotManager, addAccounts, createSnapshotManager } from '../fixtures/snapshot_manager.js';
18
+ import { type ISnapshotManager, createSnapshotManager, deployAccounts } from '../fixtures/snapshot_manager.js';
19
19
 
20
20
  const { E2E_DATA_PATH: dataPath } = process.env;
21
21
 
@@ -47,14 +47,9 @@ export class DeployTest {
47
47
  private async applyInitialAccountSnapshot() {
48
48
  await this.snapshotManager.snapshot(
49
49
  'initial_account',
50
- addAccounts(1, this.logger),
51
- async ({ accountKeys }, { pxe }) => {
52
- this.wallets = await Promise.all(
53
- accountKeys.map(async ak => {
54
- const account = await getSchnorrAccount(pxe, ak[0], ak[1], 1);
55
- return account.getWallet();
56
- }),
57
- );
50
+ deployAccounts(1, this.logger),
51
+ async ({ deployedAccounts }, { pxe }) => {
52
+ this.wallets = await Promise.all(deployedAccounts.map(a => getSchnorrWallet(pxe, a.address, a.signingKey)));
58
53
  this.wallets.forEach((w, i) => this.logger.verbose(`Wallet ${i} address: ${w.getAddress()}`));
59
54
  this.wallet = this.wallets[0];
60
55
  },
@@ -0,0 +1,217 @@
1
+ import { AztecNodeService } from '@aztec/aztec-node';
2
+ import { Fr, type Logger, getTimestampRangeForEpoch, retryUntil, sleep } from '@aztec/aztec.js';
3
+ import { ChainMonitor } from '@aztec/aztec.js/ethereum';
4
+ import { RollupContract } from '@aztec/ethereum/contracts';
5
+ import { DelayedTxUtils, type Delayer, waitUntilL1Timestamp } from '@aztec/ethereum/test';
6
+ import { randomBytes } from '@aztec/foundation/crypto';
7
+ import { withLogNameSuffix } from '@aztec/foundation/log';
8
+ import { ProverNode, ProverNodePublisher } from '@aztec/prover-node';
9
+ import type { TestProverNode } from '@aztec/prover-node/test';
10
+ import type { SequencerPublisher } from '@aztec/sequencer-client';
11
+ import type { TestSequencerClient } from '@aztec/sequencer-client/test';
12
+ import type { L2BlockNumber } from '@aztec/stdlib/block';
13
+ import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
14
+ import { MerkleTreeId } from '@aztec/stdlib/trees';
15
+
16
+ import { join } from 'path';
17
+ import type { Hex, PublicClient } from 'viem';
18
+
19
+ import {
20
+ type EndToEndContext,
21
+ type SetupOptions,
22
+ createAndSyncProverNode,
23
+ getPrivateKeyFromIndex,
24
+ setup,
25
+ } from '../fixtures/utils.js';
26
+
27
+ // This can be lowered to as much as 2s in non-CI
28
+ export const L1_BLOCK_TIME_IN_S = process.env.L1_BLOCK_TIME ? parseInt(process.env.L1_BLOCK_TIME) : 8;
29
+ export const EPOCH_DURATION_IN_L2_SLOTS = 4;
30
+ export const L2_SLOT_DURATION_IN_L1_SLOTS = 2;
31
+ export const WORLD_STATE_BLOCK_HISTORY = 2;
32
+ export const WORLD_STATE_BLOCK_CHECK_INTERVAL = 50;
33
+ export const ARCHIVER_POLL_INTERVAL = 50;
34
+
35
+ export type EpochsTestOpts = Partial<Pick<SetupOptions, 'startProverNode'>>;
36
+
37
+ /**
38
+ * Tests building of epochs using fast block times and short epochs.
39
+ * Spawns an aztec node and a prover node with fake proofs.
40
+ * Sequencer is allowed to build empty blocks.
41
+ */
42
+ export class EpochsTestContext {
43
+ public context!: EndToEndContext;
44
+ public l1Client!: PublicClient;
45
+ public rollup!: RollupContract;
46
+ public constants!: L1RollupConstants;
47
+ public logger!: Logger;
48
+ public monitor!: ChainMonitor;
49
+ public proverDelayer!: Delayer;
50
+ public sequencerDelayer!: Delayer;
51
+
52
+ public proverNodes: ProverNode[] = [];
53
+ public nodes: AztecNodeService[] = [];
54
+
55
+ public static async setup(opts: EpochsTestOpts = {}) {
56
+ const test = new EpochsTestContext();
57
+ await test.setup(opts);
58
+ return test;
59
+ }
60
+
61
+ public async setup(opts: EpochsTestOpts = {}) {
62
+ // Set up system without any account nor protocol contracts
63
+ // and with faster block times and shorter epochs.
64
+ const context = await setup(0, {
65
+ checkIntervalMs: 50,
66
+ archiverPollingIntervalMS: ARCHIVER_POLL_INTERVAL,
67
+ worldStateBlockCheckIntervalMS: WORLD_STATE_BLOCK_CHECK_INTERVAL,
68
+ skipProtocolContracts: true,
69
+ salt: 1,
70
+ aztecEpochDuration: EPOCH_DURATION_IN_L2_SLOTS,
71
+ aztecSlotDuration: L1_BLOCK_TIME_IN_S * L2_SLOT_DURATION_IN_L1_SLOTS,
72
+ ethereumSlotDuration: L1_BLOCK_TIME_IN_S,
73
+ aztecProofSubmissionWindow: EPOCH_DURATION_IN_L2_SLOTS * 2 - 1,
74
+ minTxsPerBlock: 0,
75
+ realProofs: false,
76
+ startProverNode: true,
77
+ // We use numeric incremental prover ids for simplicity, but we can switch to
78
+ // using the prover's eth address if the proverId is used for something in the rollup contract
79
+ proverId: Fr.fromString('1'),
80
+ // This must be enough so that the tx from the prover is delayed properly,
81
+ // but not so much to hang the sequencer and timeout the teardown
82
+ txPropagationMaxQueryAttempts: 12,
83
+ worldStateBlockHistory: WORLD_STATE_BLOCK_HISTORY,
84
+ ...opts,
85
+ });
86
+
87
+ this.context = context;
88
+ this.proverNodes = context.proverNode ? [context.proverNode] : [];
89
+ this.nodes = context.aztecNode ? [context.aztecNode as AztecNodeService] : [];
90
+ this.logger = context.logger;
91
+ this.l1Client = context.deployL1ContractsValues.publicClient;
92
+ this.rollup = RollupContract.getFromConfig(context.config);
93
+
94
+ // Loop that tracks L1 and L2 block numbers and logs whenever there's a new one.
95
+ this.monitor = new ChainMonitor(this.rollup, this.logger).start();
96
+
97
+ // This is hideous.
98
+ // We ought to have a definite reference to the l1TxUtils that we're using in both places, provided by the test context.
99
+ this.proverDelayer = context.proverNode
100
+ ? (((context.proverNode as TestProverNode).publisher as ProverNodePublisher).l1TxUtils as DelayedTxUtils).delayer!
101
+ : undefined!;
102
+ this.sequencerDelayer = (
103
+ ((context.sequencer as TestSequencerClient).sequencer.publisher as SequencerPublisher).l1TxUtils as DelayedTxUtils
104
+ ).delayer!;
105
+
106
+ if ((context.proverNode && !this.proverDelayer) || !this.sequencerDelayer) {
107
+ throw new Error(`Could not find prover or sequencer delayer`);
108
+ }
109
+
110
+ // Constants used for time calculation
111
+ this.constants = {
112
+ epochDuration: EPOCH_DURATION_IN_L2_SLOTS,
113
+ slotDuration: L1_BLOCK_TIME_IN_S * L2_SLOT_DURATION_IN_L1_SLOTS,
114
+ l1StartBlock: await this.rollup.getL1StartBlock(),
115
+ l1GenesisTime: await this.rollup.getL1GenesisTime(),
116
+ ethereumSlotDuration: L1_BLOCK_TIME_IN_S,
117
+ };
118
+
119
+ this.logger.info(
120
+ `L2 genesis at L1 block ${this.constants.l1StartBlock} (timestamp ${this.constants.l1GenesisTime})`,
121
+ );
122
+ }
123
+
124
+ public async teardown() {
125
+ this.monitor.stop();
126
+ await Promise.all(this.proverNodes.map(node => node.stop()));
127
+ await Promise.all(this.nodes.map(node => node.stop()));
128
+ await this.context.teardown();
129
+ }
130
+
131
+ public async createProverNode() {
132
+ this.logger.warn('Creating and syncing a simulated prover node...');
133
+ const proverNodePrivateKey = this.getNextPrivateKey();
134
+ const suffix = (this.proverNodes.length + 1).toString();
135
+ const proverNode = await withLogNameSuffix(suffix, () =>
136
+ createAndSyncProverNode(
137
+ proverNodePrivateKey,
138
+ { ...this.context.config, proverId: Fr.fromString(suffix) },
139
+ this.context.aztecNode,
140
+ join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')),
141
+ ),
142
+ );
143
+ this.proverNodes.push(proverNode);
144
+ return proverNode;
145
+ }
146
+
147
+ public async createNonValidatorNode() {
148
+ this.logger.warn('Creating and syncing a node without a validator...');
149
+ const suffix = (this.nodes.length + 1).toString();
150
+ const node = await withLogNameSuffix(suffix, () =>
151
+ AztecNodeService.createAndSync({
152
+ ...this.context.config,
153
+ disableValidator: true,
154
+ dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')),
155
+ }),
156
+ );
157
+ this.nodes.push(node);
158
+ return node;
159
+ }
160
+
161
+ private getNextPrivateKey(): Hex {
162
+ const key = getPrivateKeyFromIndex(this.nodes.length + this.proverNodes.length + 1);
163
+ return `0x${key!.toString('hex')}`;
164
+ }
165
+
166
+ /** Waits until the epoch begins (ie until the immediately previous L1 block is mined). */
167
+ public async waitUntilEpochStarts(epoch: number) {
168
+ const [start] = getTimestampRangeForEpoch(BigInt(epoch), this.constants);
169
+ this.logger.info(`Waiting until L1 timestamp ${start} is reached as the start of epoch ${epoch}`);
170
+ await waitUntilL1Timestamp(this.l1Client, start - BigInt(L1_BLOCK_TIME_IN_S));
171
+ return start;
172
+ }
173
+
174
+ /** Waits until the given L2 block number is mined. */
175
+ public async waitUntilL2BlockNumber(target: number, timeout = 60) {
176
+ await retryUntil(
177
+ () => Promise.resolve(target === this.monitor.l2BlockNumber),
178
+ `Wait until L2 block ${target}`,
179
+ timeout,
180
+ 0.1,
181
+ );
182
+ }
183
+
184
+ /** Waits until the given L2 block number is marked as proven. */
185
+ public async waitUntilProvenL2BlockNumber(t: number, timeout = 60) {
186
+ await retryUntil(
187
+ () => Promise.resolve(t === this.monitor.l2ProvenBlockNumber),
188
+ `Wait proven L2 block ${t}`,
189
+ timeout,
190
+ 0.1,
191
+ );
192
+ }
193
+
194
+ /** Waits for the aztec node to sync to the target block number. */
195
+ public async waitForNodeToSync(blockNumber: number, type: 'finalised' | 'historic') {
196
+ const waitTime = ARCHIVER_POLL_INTERVAL + WORLD_STATE_BLOCK_CHECK_INTERVAL;
197
+ let synched = false;
198
+ while (!synched) {
199
+ await sleep(waitTime);
200
+ const syncState = await this.context.aztecNode.getWorldStateSyncStatus();
201
+ if (type === 'finalised') {
202
+ synched = syncState.finalisedBlockNumber >= blockNumber;
203
+ } else {
204
+ synched = syncState.oldestHistoricBlockNumber >= blockNumber;
205
+ }
206
+ }
207
+ }
208
+
209
+ /** Verifies whether the given block number is found on the aztec node. */
210
+ public async verifyHistoricBlock(blockNumber: L2BlockNumber, expectedSuccess: boolean) {
211
+ const result = await this.context.aztecNode
212
+ .findBlockNumbersForIndexes(blockNumber, MerkleTreeId.NULLIFIER_TREE, [0n])
213
+ .then(_ => true)
214
+ .catch(_ => false);
215
+ expect(result).toBe(expectedSuccess);
216
+ }
217
+ }
@@ -1,19 +1,19 @@
1
- import { getSchnorrAccount } from '@aztec/accounts/schnorr';
1
+ import { getSchnorrWallet } from '@aztec/accounts/schnorr';
2
2
  import {
3
3
  type AccountWallet,
4
4
  type AztecAddress,
5
5
  type AztecNode,
6
+ ChainMonitor,
6
7
  CheatCodes,
7
8
  type Logger,
8
9
  type PXE,
9
- SignerlessWallet,
10
10
  createLogger,
11
11
  sleep,
12
12
  } from '@aztec/aztec.js';
13
- import { DefaultMultiCallEntrypoint } from '@aztec/aztec.js/entrypoint';
14
- import { EthAddress, FEE_FUNDING_FOR_TESTER_ACCOUNT, GasSettings, computePartialAddress } from '@aztec/circuits.js';
15
- import { createL1Clients } from '@aztec/ethereum';
16
- import { TestERC20Abi } from '@aztec/l1-artifacts';
13
+ import { FEE_FUNDING_FOR_TESTER_ACCOUNT } from '@aztec/constants';
14
+ import { type DeployL1ContractsArgs, RollupContract, createL1Clients } from '@aztec/ethereum';
15
+ import { EthAddress } from '@aztec/foundation/eth-address';
16
+ import { RollupAbi, TestERC20Abi } from '@aztec/l1-artifacts';
17
17
  import { AppSubscriptionContract } from '@aztec/noir-contracts.js/AppSubscription';
18
18
  import { CounterContract } from '@aztec/noir-contracts.js/Counter';
19
19
  import { FPCContract } from '@aztec/noir-contracts.js/FPC';
@@ -21,14 +21,22 @@ import { FeeJuiceContract } from '@aztec/noir-contracts.js/FeeJuice';
21
21
  import { TokenContract as BananaCoin } from '@aztec/noir-contracts.js/Token';
22
22
  import { ProtocolContractAddress } from '@aztec/protocol-contracts';
23
23
  import { getCanonicalFeeJuice } from '@aztec/protocol-contracts/fee-juice';
24
+ import { computePartialAddress } from '@aztec/stdlib/contract';
25
+ import { GasSettings } from '@aztec/stdlib/gas';
24
26
 
25
27
  import { getContract } from 'viem';
26
28
 
27
29
  import { MNEMONIC } from '../fixtures/fixtures.js';
28
- import { type ISnapshotManager, addAccounts, createSnapshotManager } from '../fixtures/snapshot_manager.js';
30
+ import {
31
+ type ISnapshotManager,
32
+ type SubsystemsContext,
33
+ createSnapshotManager,
34
+ deployAccounts,
35
+ } from '../fixtures/snapshot_manager.js';
29
36
  import { mintTokensToPrivate } from '../fixtures/token_utils.js';
30
37
  import {
31
38
  type BalancesFn,
39
+ type SetupOptions,
32
40
  ensureAccountsPubliclyDeployed,
33
41
  getBalancesFn,
34
42
  setupCanonicalFeeJuice,
@@ -73,30 +81,56 @@ export class FeesTest {
73
81
  public subscriptionContract!: AppSubscriptionContract;
74
82
  public feeJuiceBridgeTestHarness!: GasBridgingTestHarness;
75
83
 
84
+ public context!: SubsystemsContext;
85
+ public chainMonitor!: ChainMonitor;
86
+
76
87
  public getCoinbaseBalance!: () => Promise<bigint>;
88
+ public getCoinbaseSequencerRewards!: () => Promise<bigint>;
77
89
  public getGasBalanceFn!: BalancesFn;
78
90
  public getBananaPublicBalanceFn!: BalancesFn;
79
91
  public getBananaPrivateBalanceFn!: BalancesFn;
92
+ public getProverFee!: (blockNumber: number) => Promise<bigint>;
80
93
 
81
94
  public readonly ALICE_INITIAL_BANANAS = BigInt(1e22);
82
95
  public readonly SUBSCRIPTION_AMOUNT = BigInt(1e19);
83
96
  public readonly APP_SPONSORED_TX_GAS_LIMIT = BigInt(10e9);
84
97
 
85
- constructor(testName: string) {
98
+ constructor(
99
+ testName: string,
100
+ private numberOfAccounts = 3,
101
+ setupOptions: Partial<SetupOptions & DeployL1ContractsArgs> = {},
102
+ ) {
103
+ if (!numberOfAccounts) {
104
+ throw new Error('There must be at least 1 initial account.');
105
+ }
86
106
  this.logger = createLogger(`e2e:e2e_fees:${testName}`);
87
- this.snapshotManager = createSnapshotManager(`e2e_fees/${testName}`, dataPath);
107
+ this.snapshotManager = createSnapshotManager(
108
+ `e2e_fees/${testName}-${numberOfAccounts}`,
109
+ dataPath,
110
+ { startProverNode: true, ...setupOptions },
111
+ { ...setupOptions },
112
+ );
88
113
  }
89
114
 
90
115
  async setup() {
91
116
  const context = await this.snapshotManager.setup();
92
117
  await context.aztecNode.setConfig({ feeRecipient: this.sequencerAddress, coinbase: this.coinbase });
118
+
119
+ const rollupContract = RollupContract.getFromConfig(context.aztecNodeConfig);
120
+ this.chainMonitor = new ChainMonitor(rollupContract, this.logger, 200).start();
121
+
93
122
  return this;
94
123
  }
95
124
 
96
125
  async teardown() {
126
+ this.chainMonitor.stop();
97
127
  await this.snapshotManager.teardown();
98
128
  }
99
129
 
130
+ setIsMarkingAsProven(b: boolean) {
131
+ this.context.watcher.setIsMarkingAsProven(b);
132
+ }
133
+
100
134
  async catchUpProvenChain() {
101
135
  const bn = await this.aztecNode.getBlockNumber();
102
136
  while ((await this.aztecNode.getProvenBlockNumber()) < bn) {
@@ -130,31 +164,29 @@ export class FeesTest {
130
164
  async applyInitialAccountsSnapshot() {
131
165
  await this.snapshotManager.snapshot(
132
166
  'initial_accounts',
133
- addAccounts(3, this.logger),
134
- async ({ accountKeys }, { pxe, aztecNode, aztecNodeConfig }) => {
167
+ deployAccounts(this.numberOfAccounts, this.logger),
168
+ async ({ deployedAccounts }, { pxe, aztecNode, aztecNodeConfig }) => {
135
169
  this.pxe = pxe;
136
170
  this.aztecNode = aztecNode;
137
171
  this.gasSettings = GasSettings.default({ maxFeesPerGas: (await this.aztecNode.getCurrentBaseFees()).mul(2) });
138
- this.cheatCodes = await CheatCodes.create(aztecNodeConfig.l1RpcUrl, pxe);
139
- const accountManagers = await Promise.all(accountKeys.map(ak => getSchnorrAccount(pxe, ak[0], ak[1], 1)));
140
- await Promise.all(accountManagers.map(a => a.register()));
141
- this.wallets = await Promise.all(accountManagers.map(a => a.getWallet()));
172
+ this.cheatCodes = await CheatCodes.create(aztecNodeConfig.l1RpcUrls, pxe);
173
+ this.wallets = await Promise.all(deployedAccounts.map(a => getSchnorrWallet(pxe, a.address, a.signingKey)));
142
174
  this.wallets.forEach((w, i) => this.logger.verbose(`Wallet ${i} address: ${w.getAddress()}`));
143
175
  [this.aliceWallet, this.bobWallet] = this.wallets.slice(0, 2);
144
176
  [this.aliceAddress, this.bobAddress, this.sequencerAddress] = this.wallets.map(w => w.getAddress());
145
177
 
146
178
  // We set Alice as the FPC admin to avoid the need for deployment of another account.
147
179
  this.fpcAdmin = this.aliceAddress;
180
+
148
181
  const canonicalFeeJuice = await getCanonicalFeeJuice();
149
182
  this.feeJuiceContract = await FeeJuiceContract.at(canonicalFeeJuice.address, this.aliceWallet);
150
- const bobInstance = (await this.bobWallet.getContractMetadata(this.bobAddress)).contractInstance;
151
- if (!bobInstance) {
152
- throw new Error('Bob instance not found');
183
+ if (this.numberOfAccounts > 1) {
184
+ const bobInstance = (await this.bobWallet.getContractMetadata(this.bobAddress)).contractInstance;
185
+ await this.aliceWallet.registerAccount(deployedAccounts[1].secret, await computePartialAddress(bobInstance!));
153
186
  }
154
- await this.aliceWallet.registerAccount(accountKeys[1][0], await computePartialAddress(bobInstance));
155
187
  this.coinbase = EthAddress.random();
156
188
 
157
- const { publicClient, walletClient } = createL1Clients(aztecNodeConfig.l1RpcUrl, MNEMONIC);
189
+ const { publicClient, walletClient } = createL1Clients(aztecNodeConfig.l1RpcUrls, MNEMONIC);
158
190
  this.feeJuiceBridgeTestHarness = await FeeJuicePortalTestingHarnessFactory.create({
159
191
  aztecNode: aztecNode,
160
192
  pxeService: pxe,
@@ -177,19 +209,16 @@ export class FeesTest {
177
209
  await this.snapshotManager.snapshot(
178
210
  'setup_fee_juice',
179
211
  async context => {
180
- await setupCanonicalFeeJuice(
181
- new SignerlessWallet(
182
- context.pxe,
183
- new DefaultMultiCallEntrypoint(context.aztecNodeConfig.l1ChainId, context.aztecNodeConfig.version),
184
- ),
185
- );
212
+ await setupCanonicalFeeJuice(context.pxe);
186
213
  },
187
214
  async (_data, context) => {
215
+ this.context = context;
216
+
188
217
  this.feeJuiceContract = await FeeJuiceContract.at(ProtocolContractAddress.FeeJuice, this.aliceWallet);
189
218
 
190
219
  this.getGasBalanceFn = getBalancesFn('⛽', this.feeJuiceContract.methods.balance_of_public, this.logger);
191
220
 
192
- const { publicClient, walletClient } = createL1Clients(context.aztecNodeConfig.l1RpcUrl, MNEMONIC);
221
+ const { publicClient, walletClient } = createL1Clients(context.aztecNodeConfig.l1RpcUrls, MNEMONIC);
193
222
  this.feeJuiceBridgeTestHarness = await FeeJuicePortalTestingHarnessFactory.create({
194
223
  aztecNode: context.aztecNode,
195
224
  pxeService: context.pxe,
@@ -238,6 +267,7 @@ export class FeesTest {
238
267
  bananaFPCAddress: bananaFPC.address,
239
268
  feeJuiceAddress: feeJuiceContract.address,
240
269
  l1FeeJuiceAddress: this.feeJuiceBridgeTestHarness.l1FeeJuiceAddress,
270
+ rollupAddress: context.deployL1ContractsValues.l1ContractAddresses.rollupAddress,
241
271
  };
242
272
  },
243
273
  async (data, context) => {
@@ -253,7 +283,7 @@ export class FeesTest {
253
283
  );
254
284
 
255
285
  this.getCoinbaseBalance = async () => {
256
- const { walletClient } = createL1Clients(context.aztecNodeConfig.l1RpcUrl, MNEMONIC);
286
+ const { walletClient } = createL1Clients(context.aztecNodeConfig.l1RpcUrls, MNEMONIC);
257
287
  const gasL1 = getContract({
258
288
  address: data.l1FeeJuiceAddress.toString(),
259
289
  abi: TestERC20Abi,
@@ -261,6 +291,32 @@ export class FeesTest {
261
291
  });
262
292
  return await gasL1.read.balanceOf([this.coinbase.toString()]);
263
293
  };
294
+
295
+ this.getCoinbaseSequencerRewards = async () => {
296
+ const { walletClient } = createL1Clients(context.aztecNodeConfig.l1RpcUrls, MNEMONIC);
297
+ const rollup = getContract({
298
+ address: data.rollupAddress.toString(),
299
+ abi: RollupAbi,
300
+ client: walletClient,
301
+ });
302
+
303
+ return await rollup.read.getSequencerRewards([this.coinbase.toString()]);
304
+ };
305
+
306
+ this.getProverFee = async (blockNumber: number) => {
307
+ const { walletClient } = createL1Clients(context.aztecNodeConfig.l1RpcUrls, MNEMONIC);
308
+ const rollup = getContract({
309
+ address: data.rollupAddress.toString(),
310
+ abi: RollupAbi,
311
+ client: walletClient,
312
+ });
313
+
314
+ const provingCostPerMana = await rollup.read.getProvingCostPerManaInFeeAsset();
315
+
316
+ const block = await this.pxe.getBlock(blockNumber);
317
+ const mana = block!.header.totalManaUsed.toBigInt();
318
+ return mana * provingCostPerMana;
319
+ };
264
320
  },
265
321
  );
266
322
  }
@@ -286,16 +342,6 @@ export class FeesTest {
286
342
  );
287
343
  }
288
344
 
289
- public async applyFundAliceWithFeeJuice() {
290
- await this.snapshotManager.snapshot(
291
- 'fund_alice_with_fee_juice',
292
- async () => {
293
- await this.mintAndBridgeFeeJuice(this.aliceAddress, FEE_FUNDING_FOR_TESTER_ACCOUNT);
294
- },
295
- () => Promise.resolve(),
296
- );
297
- }
298
-
299
345
  public async applySetupSubscription() {
300
346
  await this.snapshotManager.snapshot(
301
347
  'setup_subscription',
@@ -1,4 +1,4 @@
1
- import { getSchnorrAccount } from '@aztec/accounts/schnorr';
1
+ import { getSchnorrWallet } from '@aztec/accounts/schnorr';
2
2
  import { type AccountWallet, type CompleteAddress, type Logger, type PXE, createLogger } from '@aztec/aztec.js';
3
3
  import { ChildContract } from '@aztec/noir-contracts.js/Child';
4
4
  import { ParentContract } from '@aztec/noir-contracts.js/Parent';
@@ -6,8 +6,8 @@ import { ParentContract } from '@aztec/noir-contracts.js/Parent';
6
6
  import {
7
7
  type ISnapshotManager,
8
8
  type SubsystemsContext,
9
- addAccounts,
10
9
  createSnapshotManager,
10
+ deployAccounts,
11
11
  publicDeployAccounts,
12
12
  } from '../fixtures/snapshot_manager.js';
13
13
 
@@ -23,9 +23,9 @@ export class NestedContractTest {
23
23
  parentContract!: ParentContract;
24
24
  childContract!: ChildContract;
25
25
 
26
- constructor(testName: string) {
26
+ constructor(testName: string, private numberOfAccounts = 1) {
27
27
  this.logger = createLogger(`e2e:e2e_nested_contract:${testName}`);
28
- this.snapshotManager = createSnapshotManager(`e2e_nested_contract/${testName}`, dataPath);
28
+ this.snapshotManager = createSnapshotManager(`e2e_nested_contract/${testName}-${numberOfAccounts}`, dataPath);
29
29
  }
30
30
 
31
31
  /**
@@ -34,18 +34,16 @@ export class NestedContractTest {
34
34
  * 2. Publicly deploy accounts
35
35
  */
36
36
  async applyBaseSnapshots() {
37
- await this.snapshotManager.snapshot('3_accounts', addAccounts(3, this.logger), async ({ accountKeys }, { pxe }) => {
38
- this.wallets = await Promise.all(
39
- accountKeys.map(async ak => {
40
- const account = await getSchnorrAccount(pxe, ak[0], ak[1], 1);
41
- return account.getWallet();
42
- }),
43
- );
44
- this.accounts = await pxe.getRegisteredAccounts();
45
- this.wallets.forEach((w, i) => this.logger.verbose(`Wallet ${i} address: ${w.getAddress()}`));
46
-
47
- this.pxe = pxe;
48
- });
37
+ await this.snapshotManager.snapshot(
38
+ 'accounts',
39
+ deployAccounts(this.numberOfAccounts, this.logger),
40
+ async ({ deployedAccounts }, { pxe }) => {
41
+ this.wallets = await Promise.all(deployedAccounts.map(a => getSchnorrWallet(pxe, a.address, a.signingKey)));
42
+ this.accounts = await pxe.getRegisteredAccounts();
43
+ this.wallets.forEach((w, i) => this.logger.verbose(`Wallet ${i} address: ${w.getAddress()}`));
44
+ this.pxe = pxe;
45
+ },
46
+ );
49
47
 
50
48
  await this.snapshotManager.snapshot(
51
49
  'public_deploy',