@aztec/aztec 0.0.1-commit.03f7ef2 → 0.0.1-commit.08c5969dc

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 (66) hide show
  1. package/dest/bin/index.js +2 -0
  2. package/dest/cli/aztec_start_action.d.ts +1 -1
  3. package/dest/cli/aztec_start_action.d.ts.map +1 -1
  4. package/dest/cli/aztec_start_action.js +6 -1
  5. package/dest/cli/aztec_start_options.d.ts +1 -1
  6. package/dest/cli/aztec_start_options.d.ts.map +1 -1
  7. package/dest/cli/aztec_start_options.js +4 -2
  8. package/dest/cli/cli.d.ts +1 -1
  9. package/dest/cli/cli.d.ts.map +1 -1
  10. package/dest/cli/cli.js +5 -37
  11. package/dest/cli/cmds/migrate_ha_db.d.ts +3 -0
  12. package/dest/cli/cmds/migrate_ha_db.d.ts.map +1 -0
  13. package/dest/cli/cmds/migrate_ha_db.js +27 -0
  14. package/dest/cli/cmds/start_archiver.d.ts +1 -1
  15. package/dest/cli/cmds/start_archiver.d.ts.map +1 -1
  16. package/dest/cli/cmds/start_archiver.js +5 -7
  17. package/dest/cli/cmds/start_bot.d.ts +3 -3
  18. package/dest/cli/cmds/start_bot.d.ts.map +1 -1
  19. package/dest/cli/cmds/start_bot.js +9 -5
  20. package/dest/cli/cmds/start_node.js +4 -2
  21. package/dest/cli/cmds/start_p2p_bootstrap.d.ts +2 -2
  22. package/dest/cli/cmds/start_p2p_bootstrap.d.ts.map +1 -1
  23. package/dest/cli/cmds/start_p2p_bootstrap.js +1 -2
  24. package/dest/cli/cmds/start_prover_agent.d.ts +1 -1
  25. package/dest/cli/cmds/start_prover_agent.d.ts.map +1 -1
  26. package/dest/cli/cmds/start_prover_agent.js +3 -3
  27. package/dest/cli/cmds/start_prover_broker.d.ts +1 -1
  28. package/dest/cli/cmds/start_prover_broker.d.ts.map +1 -1
  29. package/dest/cli/cmds/start_prover_broker.js +2 -2
  30. package/dest/cli/util.d.ts +5 -14
  31. package/dest/cli/util.d.ts.map +1 -1
  32. package/dest/cli/util.js +11 -6
  33. package/dest/examples/token.js +5 -5
  34. package/dest/local-network/banana_fpc.d.ts +1 -1
  35. package/dest/local-network/banana_fpc.d.ts.map +1 -1
  36. package/dest/local-network/banana_fpc.js +2 -2
  37. package/dest/local-network/local-network.d.ts +2 -3
  38. package/dest/local-network/local-network.d.ts.map +1 -1
  39. package/dest/local-network/local-network.js +27 -17
  40. package/dest/testing/cheat_codes.d.ts +3 -1
  41. package/dest/testing/cheat_codes.d.ts.map +1 -1
  42. package/dest/testing/epoch_test_settler.d.ts +19 -0
  43. package/dest/testing/epoch_test_settler.d.ts.map +1 -0
  44. package/dest/testing/epoch_test_settler.js +62 -0
  45. package/dest/testing/index.d.ts +2 -1
  46. package/dest/testing/index.d.ts.map +1 -1
  47. package/dest/testing/index.js +1 -0
  48. package/package.json +35 -34
  49. package/scripts/aztec.sh +14 -7
  50. package/src/bin/index.ts +2 -0
  51. package/src/cli/aztec_start_action.ts +5 -0
  52. package/src/cli/aztec_start_options.ts +3 -1
  53. package/src/cli/cli.ts +5 -37
  54. package/src/cli/cmds/migrate_ha_db.ts +43 -0
  55. package/src/cli/cmds/start_archiver.ts +2 -13
  56. package/src/cli/cmds/start_bot.ts +8 -5
  57. package/src/cli/cmds/start_node.ts +2 -2
  58. package/src/cli/cmds/start_p2p_bootstrap.ts +2 -2
  59. package/src/cli/cmds/start_prover_agent.ts +3 -11
  60. package/src/cli/cmds/start_prover_broker.ts +5 -1
  61. package/src/cli/util.ts +15 -20
  62. package/src/examples/token.ts +5 -7
  63. package/src/local-network/banana_fpc.ts +10 -6
  64. package/src/local-network/local-network.ts +35 -21
  65. package/src/testing/epoch_test_settler.ts +71 -0
  66. package/src/testing/index.ts +1 -0
@@ -15,7 +15,7 @@ import {
15
15
  initTelemetryClient,
16
16
  telemetryClientConfigMappings,
17
17
  } from '@aztec/telemetry-client';
18
- import { TestWallet } from '@aztec/test-wallet/server';
18
+ import { EmbeddedWallet } from '@aztec/wallets/embedded';
19
19
  import { getGenesisValues } from '@aztec/world-state/testing';
20
20
 
21
21
  import { createAztecNode } from '../../local-network/index.js';
@@ -135,7 +135,7 @@ export async function startNode(
135
135
  const { addBot } = await import('./start_bot.js');
136
136
 
137
137
  const pxeConfig = extractRelevantOptions<PXEConfig & CliPXEOptions>(options, allPxeConfigMappings, 'pxe');
138
- const wallet = await TestWallet.create(node, pxeConfig);
138
+ const wallet = await EmbeddedWallet.create(node, { pxeConfig });
139
139
 
140
140
  await addBot(options, signalHandlers, services, wallet, node, telemetry, undefined);
141
141
  }
@@ -1,6 +1,6 @@
1
1
  import { jsonStringify } from '@aztec/foundation/json-rpc';
2
2
  import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
3
- import { type LogFn, createLogger } from '@aztec/foundation/log';
3
+ import type { LogFn } from '@aztec/foundation/log';
4
4
  import { createStore } from '@aztec/kv-store/lmdb-v2';
5
5
  import { type BootnodeConfig, BootstrapNode, bootnodeConfigMappings } from '@aztec/p2p';
6
6
  import { emptyChainConfig } from '@aztec/stdlib/config';
@@ -27,7 +27,7 @@ export async function startP2PBootstrap(
27
27
  const telemetryConfig = extractRelevantOptions<TelemetryClientConfig>(options, telemetryClientConfigMappings, 'tel');
28
28
  const telemetryClient = await initTelemetryClient(telemetryConfig);
29
29
 
30
- const store = await createStore('p2p-bootstrap', 1, config, createLogger('p2p:bootstrap:store'));
30
+ const store = await createStore('p2p-bootstrap', 1, config);
31
31
  const node = new BootstrapNode(store, telemetryClient);
32
32
  await node.start(config);
33
33
  signalHandlers.push(() => node.stop());
@@ -4,9 +4,9 @@ import { Agent, makeUndiciFetch } from '@aztec/foundation/json-rpc/undici';
4
4
  import type { LogFn } from '@aztec/foundation/log';
5
5
  import { buildServerCircuitProver } from '@aztec/prover-client';
6
6
  import {
7
- InlineProofStore,
8
7
  type ProverAgentConfig,
9
8
  ProvingAgent,
9
+ createProofStore,
10
10
  createProvingJobBrokerClient,
11
11
  proverAgentConfigMappings,
12
12
  } from '@aztec/prover-client/broker';
@@ -55,18 +55,10 @@ export async function startProverAgent(
55
55
 
56
56
  const telemetry = await initTelemetryClient(extractRelevantOptions(options, telemetryClientConfigMappings, 'tel'));
57
57
  const prover = await buildServerCircuitProver(config, telemetry);
58
- const proofStore = new InlineProofStore();
58
+ const proofStore = await createProofStore(config.proofStore);
59
59
  const agents = times(
60
60
  config.proverAgentCount,
61
- () =>
62
- new ProvingAgent(
63
- broker,
64
- proofStore,
65
- prover,
66
- config.proverAgentProofTypes,
67
- config.proverAgentPollIntervalMs,
68
- telemetry,
69
- ),
61
+ () => new ProvingAgent(broker, proofStore, prover, config.proverAgentProofTypes, config.proverAgentPollIntervalMs),
70
62
  );
71
63
 
72
64
  // expose all agents as individual services
@@ -5,6 +5,7 @@ import type { LogFn } from '@aztec/foundation/log';
5
5
  import {
6
6
  type ProverBrokerConfig,
7
7
  ProvingJobBrokerSchema,
8
+ ProvingJobBrokerSchemaWithDebug,
8
9
  createAndStartProvingBroker,
9
10
  proverBrokerConfigMappings,
10
11
  } from '@aztec/prover-client/broker';
@@ -59,7 +60,10 @@ export async function startProverBroker(
59
60
  );
60
61
  }
61
62
 
62
- services.proverBroker = [broker, ProvingJobBrokerSchema];
63
+ services.proverBroker = [
64
+ broker,
65
+ config.proverBrokerDebugReplayEnabled ? ProvingJobBrokerSchemaWithDebug : ProvingJobBrokerSchema,
66
+ ];
63
67
  signalHandlers.push(() => broker.stop());
64
68
 
65
69
  return { broker, config };
package/src/cli/util.ts CHANGED
@@ -2,13 +2,13 @@ import type { AztecNodeConfig } from '@aztec/aztec-node';
2
2
  import type { AccountManager } from '@aztec/aztec.js/wallet';
3
3
  import type { ViemClient } from '@aztec/ethereum/types';
4
4
  import type { ConfigMappingsType } from '@aztec/foundation/config';
5
- import { Fr } from '@aztec/foundation/curves/bn254';
6
5
  import { EthAddress } from '@aztec/foundation/eth-address';
6
+ import { jsonStringify } from '@aztec/foundation/json-rpc';
7
7
  import { type LogFn, createLogger } from '@aztec/foundation/log';
8
8
  import type { SharedNodeConfig } from '@aztec/node-lib/config';
9
9
  import type { ProverConfig } from '@aztec/stdlib/interfaces/server';
10
10
  import { getTelemetryClient } from '@aztec/telemetry-client/start';
11
- import type { TestWallet } from '@aztec/test-wallet/server';
11
+ import type { EmbeddedWallet } from '@aztec/wallets/embedded';
12
12
 
13
13
  import chalk from 'chalk';
14
14
  import type { Command } from 'commander';
@@ -36,7 +36,7 @@ export function shutdown(logFn: LogFn, exitCode: ExitCode, cb?: Array<() => Prom
36
36
 
37
37
  logFn('Shutting down...', { exitCode });
38
38
  if (cb) {
39
- shutdownPromise = Promise.allSettled(cb).then(() => process.exit(exitCode));
39
+ shutdownPromise = Promise.allSettled(cb.map(fn => fn())).then(() => process.exit(exitCode));
40
40
  } else {
41
41
  // synchronously shuts down the process
42
42
  // no need to set shutdownPromise on this branch of the if statement because no more code will be executed
@@ -68,30 +68,19 @@ export const installSignalHandlers = (logFn: LogFn, cb?: Array<() => Promise<voi
68
68
  /**
69
69
  * Creates logs for the initial accounts
70
70
  * @param accounts - The initial accounts
71
- * @param wallet - A TestWallet instance to get the registered accounts
71
+ * @param wallet - A EmbeddedWallet instance to get the registered accounts
72
72
  * @returns A string array containing the initial accounts details
73
73
  */
74
- export async function createAccountLogs(
75
- accountsWithSecretKeys: {
76
- /**
77
- * The account object
78
- */
79
- account: AccountManager;
80
- /**
81
- * The secret key of the account
82
- */
83
- secretKey: Fr;
84
- }[],
85
- wallet: TestWallet,
86
- ) {
74
+ export async function createAccountLogs(accountManagers: AccountManager[], wallet: EmbeddedWallet) {
87
75
  const registeredAccounts = await wallet.getAccounts();
88
76
  const accountLogStrings = [`Initial Accounts:\n\n`];
89
- for (const accountWithSecretKey of accountsWithSecretKeys) {
90
- const completeAddress = await accountWithSecretKey.account.getCompleteAddress();
77
+ for (const accountManager of accountManagers) {
78
+ const account = await accountManager.getAccount();
79
+ const completeAddress = account.getCompleteAddress();
91
80
  if (registeredAccounts.find(a => a.item.equals(completeAddress.address))) {
92
81
  accountLogStrings.push(` Address: ${completeAddress.address.toString()}\n`);
93
82
  accountLogStrings.push(` Partial Address: ${completeAddress.partialAddress.toString()}\n`);
94
- accountLogStrings.push(` Secret Key: ${accountWithSecretKey.secretKey.toString()}\n`);
83
+ accountLogStrings.push(` Secret Key: ${account.getSecretKey().toString()}\n`);
95
84
  accountLogStrings.push(
96
85
  ` Master nullifier public key: ${completeAddress.publicKeys.masterNullifierPublicKey.toString()}\n`,
97
86
  );
@@ -388,3 +377,9 @@ export async function setupUpdateMonitor(
388
377
 
389
378
  checker.start();
390
379
  }
380
+
381
+ export function stringifyConfig(config: object): string {
382
+ return Object.entries(config)
383
+ .map(([key, value]) => `${key}=${jsonStringify(value)}`)
384
+ .join(' ');
385
+ }
@@ -2,7 +2,7 @@ import { getInitialTestAccountsData } from '@aztec/accounts/testing';
2
2
  import { createAztecNodeClient } from '@aztec/aztec.js/node';
3
3
  import { createLogger } from '@aztec/foundation/log';
4
4
  import { TokenContract } from '@aztec/noir-contracts.js/Token';
5
- import { TestWallet } from '@aztec/test-wallet/server';
5
+ import { EmbeddedWallet } from '@aztec/wallets/embedded';
6
6
 
7
7
  const logger = createLogger('example:token');
8
8
 
@@ -19,7 +19,7 @@ const TRANSFER_AMOUNT = 33n;
19
19
  async function main() {
20
20
  logger.info('Running token contract test on HTTP interface.');
21
21
 
22
- const wallet = await TestWallet.create(node);
22
+ const wallet = await EmbeddedWallet.create(node);
23
23
 
24
24
  // During local network setup we deploy a few accounts. Below we add them to our wallet.
25
25
  const [aliceInitialAccountData, bobInitialAccountData] = await getInitialTestAccountsData();
@@ -32,14 +32,12 @@ async function main() {
32
32
  logger.info(`Fetched Alice and Bob accounts: ${alice.toString()}, ${bob.toString()}`);
33
33
 
34
34
  logger.info('Deploying Token...');
35
- const token = await TokenContract.deploy(wallet, alice, 'TokenName', 'TokenSymbol', 18)
36
- .send({ from: alice })
37
- .deployed();
35
+ const token = await TokenContract.deploy(wallet, alice, 'TokenName', 'TokenSymbol', 18).send({ from: alice });
38
36
  logger.info('Token deployed');
39
37
 
40
38
  // Mint tokens to Alice
41
39
  logger.info(`Minting ${ALICE_MINT_BALANCE} more coins to Alice...`);
42
- await token.methods.mint_to_private(alice, ALICE_MINT_BALANCE).send({ from: alice }).wait();
40
+ await token.methods.mint_to_private(alice, ALICE_MINT_BALANCE).send({ from: alice });
43
41
 
44
42
  logger.info(`${ALICE_MINT_BALANCE} tokens were successfully minted by Alice and transferred to private`);
45
43
 
@@ -48,7 +46,7 @@ async function main() {
48
46
 
49
47
  // We will now transfer tokens from Alice to Bob
50
48
  logger.info(`Transferring ${TRANSFER_AMOUNT} tokens from Alice to Bob...`);
51
- await token.methods.transfer(bob, TRANSFER_AMOUNT).send({ from: alice }).wait();
49
+ await token.methods.transfer(bob, TRANSFER_AMOUNT).send({ from: alice });
52
50
 
53
51
  // Check the new balances
54
52
  const aliceBalance = await token.methods.balance_of_private(alice).simulate({ from: alice });
@@ -49,12 +49,16 @@ export async function setupBananaFPC(initialAccounts: InitialAccountData[], wall
49
49
  const bananaCoinAddress = await getBananaCoinAddress(initialAccounts);
50
50
  const admin = getBananaAdmin(initialAccounts);
51
51
  const [bananaCoin, fpc] = await Promise.all([
52
- TokenContract.deploy(wallet, admin, bananaCoinArgs.name, bananaCoinArgs.symbol, bananaCoinArgs.decimal)
53
- .send({ from: admin, contractAddressSalt: BANANA_COIN_SALT, universalDeploy: true })
54
- .deployed(),
55
- FPCContract.deploy(wallet, bananaCoinAddress, admin)
56
- .send({ from: admin, contractAddressSalt: BANANA_FPC_SALT, universalDeploy: true })
57
- .deployed(),
52
+ TokenContract.deploy(wallet, admin, bananaCoinArgs.name, bananaCoinArgs.symbol, bananaCoinArgs.decimal).send({
53
+ from: admin,
54
+ contractAddressSalt: BANANA_COIN_SALT,
55
+ universalDeploy: true,
56
+ }),
57
+ FPCContract.deploy(wallet, bananaCoinAddress, admin).send({
58
+ from: admin,
59
+ contractAddressSalt: BANANA_FPC_SALT,
60
+ universalDeploy: true,
61
+ }),
58
62
  ]);
59
63
 
60
64
  log(`BananaCoin: ${bananaCoin.address}`);
@@ -24,7 +24,8 @@ import {
24
24
  getConfigEnvVars as getTelemetryClientConfig,
25
25
  initTelemetryClient,
26
26
  } from '@aztec/telemetry-client';
27
- import { TestWallet, deployFundedSchnorrAccounts } from '@aztec/test-wallet/server';
27
+ import { EmbeddedWallet } from '@aztec/wallets/embedded';
28
+ import { deployFundedSchnorrAccounts } from '@aztec/wallets/testing';
28
29
  import { getGenesisValues } from '@aztec/world-state/testing';
29
30
 
30
31
  import { type Hex, createPublicClient, fallback, http as httpViemTransport } from 'viem';
@@ -34,6 +35,7 @@ import { foundry } from 'viem/chains';
34
35
  import { createAccountLogs } from '../cli/util.js';
35
36
  import { DefaultMnemonic } from '../mnemonic.js';
36
37
  import { AnvilTestWatcher } from '../testing/anvil_test_watcher.js';
38
+ import { EpochTestSettler } from '../testing/epoch_test_settler.js';
37
39
  import { getBananaFPCAddress, setupBananaFPC } from './banana_fpc.js';
38
40
  import { getSponsoredFPCAddress } from './sponsored_fpc.js';
39
41
 
@@ -50,7 +52,6 @@ export async function deployContractsToL1(
50
52
  aztecNodeConfig: AztecNodeConfig,
51
53
  privateKey: Hex,
52
54
  opts: {
53
- assumeProvenThroughBlockNumber?: number;
54
55
  genesisArchiveRoot?: Fr;
55
56
  feeJuicePortalInitialBalance?: bigint;
56
57
  } = {},
@@ -97,7 +98,11 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
97
98
  if ((config.l1RpcUrls?.length || 0) > 1) {
98
99
  logger.warn(`Multiple L1 RPC URLs provided. Local networks will only use the first one: ${l1RpcUrl}`);
99
100
  }
100
- const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars(), ...config };
101
+
102
+ const aztecNodeConfig: AztecNodeConfig = {
103
+ ...getConfigEnvVars(),
104
+ ...config,
105
+ };
101
106
  const hdAccount = mnemonicToAccount(config.l1Mnemonic || DefaultMnemonic);
102
107
  if (
103
108
  aztecNodeConfig.publisherPrivateKeys == undefined ||
@@ -134,18 +139,20 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
134
139
  : [];
135
140
  const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues(fundedAddresses);
136
141
 
137
- let watcher: AnvilTestWatcher | undefined = undefined;
138
142
  const dateProvider = new TestDateProvider();
143
+
144
+ let cheatcodes: EthCheatCodes | undefined;
145
+ let rollupAddress: EthAddress | undefined;
146
+ let watcher: AnvilTestWatcher | undefined;
139
147
  if (!aztecNodeConfig.p2pEnabled) {
140
- const l1ContractAddresses = await deployContractsToL1(
148
+ ({ rollupAddress } = await deployContractsToL1(
141
149
  aztecNodeConfig,
142
150
  aztecNodeConfig.validatorPrivateKeys.getValue()[0],
143
151
  {
144
- assumeProvenThroughBlockNumber: Number.MAX_SAFE_INTEGER,
145
152
  genesisArchiveRoot,
146
153
  feeJuicePortalInitialBalance: fundingNeeded,
147
154
  },
148
- );
155
+ ));
149
156
 
150
157
  const chain =
151
158
  aztecNodeConfig.l1RpcUrls.length > 0
@@ -157,13 +164,12 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
157
164
  transport: fallback([httpViemTransport(l1RpcUrl)]) as any,
158
165
  });
159
166
 
160
- watcher = new AnvilTestWatcher(
161
- new EthCheatCodes([l1RpcUrl], dateProvider),
162
- l1ContractAddresses.rollupAddress,
163
- publicClient,
164
- dateProvider,
165
- );
167
+ cheatcodes = new EthCheatCodes([l1RpcUrl], dateProvider);
168
+
169
+ watcher = new AnvilTestWatcher(cheatcodes, rollupAddress, publicClient, dateProvider);
166
170
  watcher.setisLocalNetwork(true);
171
+ watcher.setIsMarkingAsProven(false); // Do not mark as proven in the watcher. It's marked in the epochTestSettler after the out hash is set.
172
+
167
173
  await watcher.start();
168
174
  }
169
175
 
@@ -172,17 +178,24 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
172
178
  const blobClient = createBlobClient();
173
179
  const node = await createAztecNode(aztecNodeConfig, { telemetry, blobClient, dateProvider }, { prefilledPublicData });
174
180
 
181
+ let epochTestSettler: EpochTestSettler | undefined;
182
+ if (!aztecNodeConfig.p2pEnabled) {
183
+ epochTestSettler = new EpochTestSettler(
184
+ cheatcodes!,
185
+ rollupAddress!,
186
+ node.getBlockSource(),
187
+ logger.createChild('epoch-settler'),
188
+ { pollingIntervalMs: 200 },
189
+ );
190
+ await epochTestSettler.start();
191
+ }
192
+
175
193
  if (initialAccounts.length) {
176
- const PXEConfig = { proverEnabled: aztecNodeConfig.realProofs };
177
- const wallet = await TestWallet.create(node, PXEConfig);
194
+ const wallet = await EmbeddedWallet.create(node, { pxeConfig: { proverEnabled: aztecNodeConfig.realProofs } });
178
195
 
179
196
  userLog('Setting up funded test accounts...');
180
- const accountManagers = await deployFundedSchnorrAccounts(wallet, node, initialAccounts);
181
- const accountsWithSecrets = accountManagers.map((manager, i) => ({
182
- account: manager,
183
- secretKey: initialAccounts[i].secret,
184
- }));
185
- const accLogs = await createAccountLogs(accountsWithSecrets, wallet);
197
+ const accountManagers = await deployFundedSchnorrAccounts(wallet, initialAccounts);
198
+ const accLogs = await createAccountLogs(accountManagers, wallet);
186
199
  userLog(accLogs.join(''));
187
200
 
188
201
  await setupBananaFPC(initialAccounts, wallet, userLog);
@@ -196,6 +209,7 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
196
209
  const stop = async () => {
197
210
  await node.stop();
198
211
  await watcher?.stop();
212
+ await epochTestSettler?.stop();
199
213
  };
200
214
 
201
215
  return { node, stop };
@@ -0,0 +1,71 @@
1
+ import { Fr } from '@aztec/aztec.js/fields';
2
+ import { type EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
3
+ import { type EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
4
+ import type { Logger } from '@aztec/foundation/log';
5
+ import { EpochMonitor } from '@aztec/prover-node';
6
+ import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
7
+ import { computeL2ToL1MembershipWitnessFromMessagesInEpoch } from '@aztec/stdlib/messaging';
8
+
9
+ export class EpochTestSettler {
10
+ private rollupCheatCodes: RollupCheatCodes;
11
+ private epochMonitor?: EpochMonitor;
12
+
13
+ constructor(
14
+ cheatcodes: EthCheatCodes,
15
+ rollupAddress: EthAddress,
16
+ private l2BlockSource: L2BlockSource,
17
+ private log: Logger,
18
+ private options: { pollingIntervalMs: number; provingDelayMs?: number },
19
+ ) {
20
+ this.rollupCheatCodes = new RollupCheatCodes(cheatcodes, { rollupAddress });
21
+ }
22
+
23
+ async start() {
24
+ const { epochDuration } = await this.rollupCheatCodes.getConfig();
25
+ this.epochMonitor = new EpochMonitor(this.l2BlockSource, { epochDuration: Number(epochDuration) }, this.options);
26
+ this.epochMonitor.start(this);
27
+ }
28
+
29
+ async stop() {
30
+ await this.epochMonitor?.stop();
31
+ }
32
+
33
+ async handleEpochReadyToProve(epoch: EpochNumber): Promise<boolean> {
34
+ const checkpointedBlocks = await this.l2BlockSource.getCheckpointedBlocksForEpoch(epoch);
35
+ const blocks = checkpointedBlocks.map(b => b.block);
36
+ this.log.info(
37
+ `Settling epoch ${epoch} with blocks ${blocks[0]?.header.getBlockNumber()} to ${blocks.at(-1)?.header.getBlockNumber()}`,
38
+ { blocks: blocks.map(b => b.toBlockInfo()) },
39
+ );
40
+ const messagesInEpoch: Fr[][][][] = [];
41
+ let previousSlotNumber = SlotNumber.ZERO;
42
+ let checkpointIndex = -1;
43
+
44
+ for (const block of blocks) {
45
+ const slotNumber = block.header.globalVariables.slotNumber;
46
+ if (slotNumber !== previousSlotNumber) {
47
+ checkpointIndex++;
48
+ messagesInEpoch[checkpointIndex] = [];
49
+ previousSlotNumber = slotNumber;
50
+ }
51
+ messagesInEpoch[checkpointIndex].push(block.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs));
52
+ }
53
+
54
+ const [firstMessage] = messagesInEpoch.flat(3);
55
+ if (firstMessage) {
56
+ const { root: outHash } = computeL2ToL1MembershipWitnessFromMessagesInEpoch(messagesInEpoch, firstMessage);
57
+ await this.rollupCheatCodes.insertOutbox(epoch, outHash.toBigInt());
58
+ } else {
59
+ this.log.info(`No L2 to L1 messages in epoch ${epoch}`);
60
+ }
61
+
62
+ const lastCheckpoint = checkpointedBlocks.at(-1)?.checkpointNumber;
63
+ if (lastCheckpoint !== undefined) {
64
+ await this.rollupCheatCodes.markAsProven(lastCheckpoint);
65
+ } else {
66
+ this.log.warn(`No checkpoint found for epoch ${epoch}`);
67
+ }
68
+
69
+ return true;
70
+ }
71
+ }
@@ -1,3 +1,4 @@
1
1
  export { AnvilTestWatcher } from './anvil_test_watcher.js';
2
2
  export { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
3
3
  export { CheatCodes } from './cheat_codes.js';
4
+ export { EpochTestSettler } from './epoch_test_settler.js';