@aztec/aztec 0.0.1-commit.5daedc8 → 0.0.1-commit.5de5ca79e

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 (136) hide show
  1. package/dest/bin/index.js +12 -5
  2. package/dest/cli/admin_api_key_store.d.ts +45 -0
  3. package/dest/cli/admin_api_key_store.d.ts.map +1 -0
  4. package/dest/cli/admin_api_key_store.js +98 -0
  5. package/dest/cli/aztec_start_action.d.ts +1 -1
  6. package/dest/cli/aztec_start_action.d.ts.map +1 -1
  7. package/dest/cli/aztec_start_action.js +65 -19
  8. package/dest/cli/aztec_start_options.d.ts +1 -1
  9. package/dest/cli/aztec_start_options.d.ts.map +1 -1
  10. package/dest/cli/aztec_start_options.js +41 -36
  11. package/dest/cli/cli.d.ts +1 -1
  12. package/dest/cli/cli.d.ts.map +1 -1
  13. package/dest/cli/cli.js +7 -52
  14. package/dest/cli/cmds/compile.d.ts +4 -0
  15. package/dest/cli/cmds/compile.d.ts.map +1 -0
  16. package/dest/cli/cmds/compile.js +166 -0
  17. package/dest/cli/cmds/migrate_ha_db.d.ts +3 -0
  18. package/dest/cli/cmds/migrate_ha_db.d.ts.map +1 -0
  19. package/dest/cli/cmds/migrate_ha_db.js +27 -0
  20. package/dest/cli/cmds/profile.d.ts +4 -0
  21. package/dest/cli/cmds/profile.d.ts.map +1 -0
  22. package/dest/cli/cmds/profile.js +8 -0
  23. package/dest/cli/cmds/profile_flamegraph.d.ts +4 -0
  24. package/dest/cli/cmds/profile_flamegraph.d.ts.map +1 -0
  25. package/dest/cli/cmds/profile_flamegraph.js +52 -0
  26. package/dest/cli/cmds/profile_gates.d.ts +4 -0
  27. package/dest/cli/cmds/profile_gates.d.ts.map +1 -0
  28. package/dest/cli/cmds/profile_gates.js +58 -0
  29. package/dest/cli/cmds/profile_utils.d.ts +18 -0
  30. package/dest/cli/cmds/profile_utils.d.ts.map +1 -0
  31. package/dest/cli/cmds/profile_utils.js +50 -0
  32. package/dest/cli/cmds/standby.d.ts +32 -0
  33. package/dest/cli/cmds/standby.d.ts.map +1 -0
  34. package/dest/cli/cmds/standby.js +97 -0
  35. package/dest/cli/cmds/start_archiver.d.ts +2 -2
  36. package/dest/cli/cmds/start_archiver.d.ts.map +1 -1
  37. package/dest/cli/cmds/start_archiver.js +12 -14
  38. package/dest/cli/cmds/start_bot.d.ts +3 -3
  39. package/dest/cli/cmds/start_bot.d.ts.map +1 -1
  40. package/dest/cli/cmds/start_bot.js +10 -6
  41. package/dest/cli/cmds/start_node.d.ts +3 -2
  42. package/dest/cli/cmds/start_node.d.ts.map +1 -1
  43. package/dest/cli/cmds/start_node.js +85 -29
  44. package/dest/cli/cmds/start_p2p_bootstrap.d.ts +2 -2
  45. package/dest/cli/cmds/start_p2p_bootstrap.d.ts.map +1 -1
  46. package/dest/cli/cmds/start_p2p_bootstrap.js +2 -3
  47. package/dest/cli/cmds/start_prover_agent.d.ts +1 -1
  48. package/dest/cli/cmds/start_prover_agent.d.ts.map +1 -1
  49. package/dest/cli/cmds/start_prover_agent.js +4 -4
  50. package/dest/cli/cmds/start_prover_broker.d.ts +1 -1
  51. package/dest/cli/cmds/start_prover_broker.d.ts.map +1 -1
  52. package/dest/cli/cmds/start_prover_broker.js +15 -9
  53. package/dest/cli/cmds/utils/artifacts.d.ts +21 -0
  54. package/dest/cli/cmds/utils/artifacts.d.ts.map +1 -0
  55. package/dest/cli/cmds/utils/artifacts.js +24 -0
  56. package/dest/cli/cmds/utils/needs_recompile.d.ts +10 -0
  57. package/dest/cli/cmds/utils/needs_recompile.d.ts.map +1 -0
  58. package/dest/cli/cmds/utils/needs_recompile.js +134 -0
  59. package/dest/cli/cmds/utils/spawn.d.ts +3 -0
  60. package/dest/cli/cmds/utils/spawn.d.ts.map +1 -0
  61. package/dest/cli/cmds/utils/spawn.js +16 -0
  62. package/dest/cli/util.d.ts +9 -20
  63. package/dest/cli/util.d.ts.map +1 -1
  64. package/dest/cli/util.js +51 -87
  65. package/dest/examples/token.js +9 -9
  66. package/dest/examples/util.d.ts +2 -2
  67. package/dest/examples/util.d.ts.map +1 -1
  68. package/dest/local-network/banana_fpc.d.ts +1 -1
  69. package/dest/local-network/banana_fpc.d.ts.map +1 -1
  70. package/dest/local-network/banana_fpc.js +4 -4
  71. package/dest/local-network/local-network.d.ts +13 -14
  72. package/dest/local-network/local-network.d.ts.map +1 -1
  73. package/dest/local-network/local-network.js +86 -43
  74. package/dest/testing/anvil_test_watcher.d.ts +10 -2
  75. package/dest/testing/anvil_test_watcher.d.ts.map +1 -1
  76. package/dest/testing/anvil_test_watcher.js +53 -16
  77. package/dest/testing/cheat_codes.d.ts +3 -1
  78. package/dest/testing/cheat_codes.d.ts.map +1 -1
  79. package/dest/testing/epoch_test_settler.d.ts +19 -0
  80. package/dest/testing/epoch_test_settler.d.ts.map +1 -0
  81. package/dest/testing/epoch_test_settler.js +61 -0
  82. package/dest/testing/index.d.ts +3 -1
  83. package/dest/testing/index.d.ts.map +1 -1
  84. package/dest/testing/index.js +2 -0
  85. package/dest/testing/token_allowed_setup.d.ts +7 -0
  86. package/dest/testing/token_allowed_setup.d.ts.map +1 -0
  87. package/dest/testing/token_allowed_setup.js +20 -0
  88. package/package.json +39 -36
  89. package/scripts/add_crate.sh +102 -0
  90. package/scripts/aztec.sh +69 -0
  91. package/scripts/init.sh +39 -0
  92. package/scripts/new.sh +83 -0
  93. package/scripts/setup_workspace.sh +68 -0
  94. package/src/bin/index.ts +13 -5
  95. package/src/cli/admin_api_key_store.ts +128 -0
  96. package/src/cli/aztec_start_action.ts +63 -14
  97. package/src/cli/aztec_start_options.ts +42 -35
  98. package/src/cli/cli.ts +11 -56
  99. package/src/cli/cmds/compile.ts +191 -0
  100. package/src/cli/cmds/migrate_ha_db.ts +43 -0
  101. package/src/cli/cmds/profile.ts +25 -0
  102. package/src/cli/cmds/profile_flamegraph.ts +64 -0
  103. package/src/cli/cmds/profile_gates.ts +68 -0
  104. package/src/cli/cmds/profile_utils.ts +58 -0
  105. package/src/cli/cmds/standby.ts +132 -0
  106. package/src/cli/cmds/start_archiver.ts +8 -19
  107. package/src/cli/cmds/start_bot.ts +9 -6
  108. package/src/cli/cmds/start_node.ts +85 -35
  109. package/src/cli/cmds/start_p2p_bootstrap.ts +3 -3
  110. package/src/cli/cmds/start_prover_agent.ts +4 -12
  111. package/src/cli/cmds/start_prover_broker.ts +20 -16
  112. package/src/cli/cmds/utils/artifacts.ts +44 -0
  113. package/src/cli/cmds/utils/needs_recompile.ts +151 -0
  114. package/src/cli/cmds/utils/spawn.ts +16 -0
  115. package/src/cli/util.ts +60 -98
  116. package/src/examples/token.ts +10 -10
  117. package/src/examples/util.ts +1 -1
  118. package/src/local-network/banana_fpc.ts +12 -8
  119. package/src/local-network/local-network.ts +120 -85
  120. package/src/testing/anvil_test_watcher.ts +61 -17
  121. package/src/testing/cheat_codes.ts +3 -2
  122. package/src/testing/epoch_test_settler.ts +70 -0
  123. package/src/testing/index.ts +2 -0
  124. package/src/testing/token_allowed_setup.ts +19 -0
  125. package/dest/cli/cmds/start_blob_sink.d.ts +0 -3
  126. package/dest/cli/cmds/start_blob_sink.d.ts.map +0 -1
  127. package/dest/cli/cmds/start_blob_sink.js +0 -33
  128. package/dest/cli/cmds/start_prover_node.d.ts +0 -7
  129. package/dest/cli/cmds/start_prover_node.d.ts.map +0 -1
  130. package/dest/cli/cmds/start_prover_node.js +0 -108
  131. package/dest/cli/release_version.d.ts +0 -2
  132. package/dest/cli/release_version.d.ts.map +0 -1
  133. package/dest/cli/release_version.js +0 -14
  134. package/src/cli/cmds/start_blob_sink.ts +0 -57
  135. package/src/cli/cmds/start_prover_node.ts +0 -124
  136. package/src/cli/release_version.ts +0 -21
@@ -1,40 +1,45 @@
1
1
  #!/usr/bin/env -S node --no-warnings
2
2
  import { getInitialTestAccountsData } from '@aztec/accounts/testing';
3
- import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node';
4
- import { EthAddress } from '@aztec/aztec.js/addresses';
5
- import { type BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client';
3
+ import { AztecNodeService } from '@aztec/aztec-node';
4
+ import { type AztecNodeConfig, getConfigEnvVars } from '@aztec/aztec-node/config';
5
+ import { Fr } from '@aztec/aztec.js/fields';
6
+ import { createLogger } from '@aztec/aztec.js/log';
7
+ import { type BlobClientInterface, createBlobClient } from '@aztec/blob-client/client';
6
8
  import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
7
- import {
8
- NULL_KEY,
9
- createEthereumChain,
10
- deployL1Contracts,
11
- deployMulticall3,
12
- getL1ContractsConfigEnvVars,
13
- waitForPublicClient,
14
- } from '@aztec/ethereum';
9
+ import { createEthereumChain } from '@aztec/ethereum/chain';
10
+ import { waitForPublicClient } from '@aztec/ethereum/client';
11
+ import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
12
+ import { NULL_KEY } from '@aztec/ethereum/constants';
13
+ import { deployAztecL1Contracts } from '@aztec/ethereum/deploy-aztec-l1-contracts';
15
14
  import { EthCheatCodes } from '@aztec/ethereum/test';
16
15
  import { SecretValue } from '@aztec/foundation/config';
17
- import { Fr } from '@aztec/foundation/fields';
18
- import { type LogFn, createLogger } from '@aztec/foundation/log';
16
+ import { EthAddress } from '@aztec/foundation/eth-address';
17
+ import type { LogFn } from '@aztec/foundation/log';
19
18
  import { DateProvider, TestDateProvider } from '@aztec/foundation/timer';
20
19
  import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
21
20
  import { protocolContractsHash } from '@aztec/protocol-contracts';
21
+ import { SequencerState } from '@aztec/sequencer-client';
22
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
23
+ import type { ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
22
24
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
23
25
  import {
24
26
  type TelemetryClient,
25
27
  getConfigEnvVars as getTelemetryClientConfig,
26
28
  initTelemetryClient,
27
29
  } from '@aztec/telemetry-client';
28
- import { TestWallet, deployFundedSchnorrAccounts } from '@aztec/test-wallet/server';
30
+ import { EmbeddedWallet } from '@aztec/wallets/embedded';
31
+ import { deployFundedSchnorrAccounts } from '@aztec/wallets/testing';
29
32
  import { getGenesisValues } from '@aztec/world-state/testing';
30
33
 
31
- import { type HDAccount, type PrivateKeyAccount, createPublicClient, fallback, http as httpViemTransport } from 'viem';
34
+ import { type Hex, createPublicClient, fallback, http as httpViemTransport } from 'viem';
32
35
  import { mnemonicToAccount, privateKeyToAddress } from 'viem/accounts';
33
36
  import { foundry } from 'viem/chains';
34
37
 
35
38
  import { createAccountLogs } from '../cli/util.js';
36
39
  import { DefaultMnemonic } from '../mnemonic.js';
37
40
  import { AnvilTestWatcher } from '../testing/anvil_test_watcher.js';
41
+ import { EpochTestSettler } from '../testing/epoch_test_settler.js';
42
+ import { getTokenAllowedSetupFunctions } from '../testing/token_allowed_setup.js';
38
43
  import { getBananaFPCAddress, setupBananaFPC } from './banana_fpc.js';
39
44
  import { getSponsoredFPCAddress } from './sponsored_fpc.js';
40
45
 
@@ -49,42 +54,25 @@ const localAnvil = foundry;
49
54
  */
50
55
  export async function deployContractsToL1(
51
56
  aztecNodeConfig: AztecNodeConfig,
52
- hdAccount: HDAccount | PrivateKeyAccount,
53
- contractDeployLogger = logger,
57
+ privateKey: Hex,
54
58
  opts: {
55
- assumeProvenThroughBlockNumber?: number;
56
- salt?: number;
57
59
  genesisArchiveRoot?: Fr;
58
60
  feeJuicePortalInitialBalance?: bigint;
59
61
  } = {},
60
62
  ) {
61
- const chain =
62
- aztecNodeConfig.l1RpcUrls.length > 0
63
- ? createEthereumChain(aztecNodeConfig.l1RpcUrls, aztecNodeConfig.l1ChainId)
64
- : { chainInfo: localAnvil };
65
-
66
63
  await waitForPublicClient(aztecNodeConfig);
67
64
 
68
- const l1Contracts = await deployL1Contracts(
69
- aztecNodeConfig.l1RpcUrls,
70
- hdAccount,
71
- chain.chainInfo,
72
- contractDeployLogger,
73
- {
74
- ...getL1ContractsConfigEnvVars(), // TODO: We should not need to be loading config from env again, caller should handle this
75
- ...aztecNodeConfig,
76
- vkTreeRoot: getVKTreeRoot(),
77
- protocolContractsHash,
78
- genesisArchiveRoot: opts.genesisArchiveRoot ?? new Fr(GENESIS_ARCHIVE_ROOT),
79
- salt: opts.salt,
80
- feeJuicePortalInitialBalance: opts.feeJuicePortalInitialBalance,
81
- aztecTargetCommitteeSize: 0, // no committee in local network
82
- slasherFlavor: 'none', // no slashing in local network
83
- realVerifier: false,
84
- },
85
- );
86
-
87
- await deployMulticall3(l1Contracts.l1Client, logger);
65
+ const l1Contracts = await deployAztecL1Contracts(aztecNodeConfig.l1RpcUrls[0], privateKey, foundry.id, {
66
+ ...getL1ContractsConfigEnvVars(), // TODO: We should not need to be loading config from env again, caller should handle this
67
+ ...aztecNodeConfig,
68
+ vkTreeRoot: getVKTreeRoot(),
69
+ protocolContractsHash,
70
+ genesisArchiveRoot: opts.genesisArchiveRoot ?? new Fr(GENESIS_ARCHIVE_ROOT),
71
+ feeJuicePortalInitialBalance: opts.feeJuicePortalInitialBalance,
72
+ aztecTargetCommitteeSize: 0, // no committee in local network
73
+ slasherFlavor: 'none', // no slashing in local network
74
+ realVerifier: false,
75
+ });
88
76
 
89
77
  aztecNodeConfig.l1Contracts = l1Contracts.l1ContractAddresses;
90
78
  aztecNodeConfig.rollupVersion = l1Contracts.rollupVersion;
@@ -96,8 +84,6 @@ export async function deployContractsToL1(
96
84
  export type LocalNetworkConfig = AztecNodeConfig & {
97
85
  /** Mnemonic used to derive the L1 deployer private key.*/
98
86
  l1Mnemonic: string;
99
- /** Salt used to deploy L1 contracts.*/
100
- deployAztecContractsSalt: string;
101
87
  /** Whether to deploy test accounts on local network start.*/
102
88
  testAccounts: boolean;
103
89
  };
@@ -116,15 +102,26 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
116
102
  if ((config.l1RpcUrls?.length || 0) > 1) {
117
103
  logger.warn(`Multiple L1 RPC URLs provided. Local networks will only use the first one: ${l1RpcUrl}`);
118
104
  }
119
- const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars(), ...config };
105
+
106
+ // The local network deploys a banana FPC with Token contracts, so include Token entries
107
+ // in the setup allowlist so FPC-based fee payments work out of the box.
108
+ const tokenAllowList = await getTokenAllowedSetupFunctions();
109
+
110
+ const aztecNodeConfig: AztecNodeConfig = {
111
+ ...getConfigEnvVars(),
112
+ ...config,
113
+ txPublicSetupAllowListExtend: [...tokenAllowList, ...(config.txPublicSetupAllowListExtend ?? [])],
114
+ };
120
115
  const hdAccount = mnemonicToAccount(config.l1Mnemonic || DefaultMnemonic);
121
116
  if (
122
- aztecNodeConfig.publisherPrivateKeys == undefined ||
123
- !aztecNodeConfig.publisherPrivateKeys.length ||
124
- aztecNodeConfig.publisherPrivateKeys[0].getValue() === NULL_KEY
117
+ aztecNodeConfig.sequencerPublisherPrivateKeys == undefined ||
118
+ !aztecNodeConfig.sequencerPublisherPrivateKeys.length ||
119
+ aztecNodeConfig.sequencerPublisherPrivateKeys[0].getValue() === NULL_KEY
125
120
  ) {
126
121
  const privKey = hdAccount.getHdKey().privateKey;
127
- aztecNodeConfig.publisherPrivateKeys = [new SecretValue(`0x${Buffer.from(privKey!).toString('hex')}` as const)];
122
+ aztecNodeConfig.sequencerPublisherPrivateKeys = [
123
+ new SecretValue(`0x${Buffer.from(privKey!).toString('hex')}` as const),
124
+ ];
128
125
  }
129
126
  if (!aztecNodeConfig.validatorPrivateKeys?.getValue().length) {
130
127
  const privKey = hdAccount.getHdKey().privateKey;
@@ -148,20 +145,28 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
148
145
 
149
146
  const bananaFPC = await getBananaFPCAddress(initialAccounts);
150
147
  const sponsoredFPC = await getSponsoredFPCAddress();
151
- const fundedAddresses = initialAccounts.length
152
- ? [...initialAccounts.map(a => a.address), bananaFPC, sponsoredFPC]
153
- : [];
148
+ const prefundAddresses = (aztecNodeConfig.prefundAddresses ?? []).map(a => AztecAddress.fromString(a));
149
+ const fundedAddresses = [
150
+ ...initialAccounts.map(a => a.address),
151
+ ...(initialAccounts.length ? [bananaFPC, sponsoredFPC] : []),
152
+ ...prefundAddresses,
153
+ ];
154
154
  const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues(fundedAddresses);
155
155
 
156
- let watcher: AnvilTestWatcher | undefined = undefined;
157
156
  const dateProvider = new TestDateProvider();
157
+
158
+ let cheatcodes: EthCheatCodes | undefined;
159
+ let rollupAddress: EthAddress | undefined;
160
+ let watcher: AnvilTestWatcher | undefined;
158
161
  if (!aztecNodeConfig.p2pEnabled) {
159
- const l1ContractAddresses = await deployContractsToL1(aztecNodeConfig, hdAccount, undefined, {
160
- assumeProvenThroughBlockNumber: Number.MAX_SAFE_INTEGER,
161
- genesisArchiveRoot,
162
- salt: config.deployAztecContractsSalt ? parseInt(config.deployAztecContractsSalt) : undefined,
163
- feeJuicePortalInitialBalance: fundingNeeded,
164
- });
162
+ ({ rollupAddress } = await deployContractsToL1(
163
+ aztecNodeConfig,
164
+ aztecNodeConfig.validatorPrivateKeys.getValue()[0],
165
+ {
166
+ genesisArchiveRoot,
167
+ feeJuicePortalInitialBalance: fundingNeeded,
168
+ },
169
+ ));
165
170
 
166
171
  const chain =
167
172
  aztecNodeConfig.l1RpcUrls.length > 0
@@ -173,36 +178,56 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
173
178
  transport: fallback([httpViemTransport(l1RpcUrl)]) as any,
174
179
  });
175
180
 
176
- watcher = new AnvilTestWatcher(
177
- new EthCheatCodes([l1RpcUrl], dateProvider),
178
- l1ContractAddresses.rollupAddress,
179
- publicClient,
180
- dateProvider,
181
- );
181
+ cheatcodes = new EthCheatCodes([l1RpcUrl], dateProvider);
182
+
183
+ watcher = new AnvilTestWatcher(cheatcodes, rollupAddress, publicClient, dateProvider);
182
184
  watcher.setisLocalNetwork(true);
185
+ watcher.setIsMarkingAsProven(false); // Do not mark as proven in the watcher. It's marked in the epochTestSettler after the out hash is set.
186
+
183
187
  await watcher.start();
184
188
  }
185
189
 
186
- const telemetry = initTelemetryClient(getTelemetryClientConfig());
187
- // Create a local blob sink client inside the local network, no http connectivity
188
- const blobSinkClient = createBlobSinkClient();
189
- const node = await createAztecNode(
190
- aztecNodeConfig,
191
- { telemetry, blobSinkClient, dateProvider },
192
- { prefilledPublicData },
193
- );
190
+ const telemetry = await initTelemetryClient(getTelemetryClientConfig());
191
+ // Create a local blob client client inside the local network, no http connectivity
192
+ const blobClient = createBlobClient();
193
+ const node = await createAztecNode(aztecNodeConfig, { telemetry, blobClient, dateProvider }, { prefilledPublicData });
194
+
195
+ // Now that the node is up, let the watcher check for pending txs so it can skip unfilled slots faster when
196
+ // transactions are waiting in the mempool. Also let it check if the sequencer is actively building, to avoid
197
+ // warping time out from under an in-progress block.
198
+ watcher?.setGetPendingTxCount(() => node.getPendingTxCount());
199
+ const sequencer = node.getSequencer()?.getSequencer();
200
+ if (sequencer) {
201
+ const idleStates: Set<string> = new Set([
202
+ SequencerState.STOPPED,
203
+ SequencerState.STOPPING,
204
+ SequencerState.IDLE,
205
+ SequencerState.SYNCHRONIZING,
206
+ ]);
207
+ watcher?.setIsSequencerBuilding(() => !idleStates.has(sequencer.getState()));
208
+ }
209
+
210
+ let epochTestSettler: EpochTestSettler | undefined;
211
+ if (!aztecNodeConfig.p2pEnabled) {
212
+ epochTestSettler = new EpochTestSettler(
213
+ cheatcodes!,
214
+ rollupAddress!,
215
+ node.getBlockSource(),
216
+ logger.createChild('epoch-settler'),
217
+ { pollingIntervalMs: 200 },
218
+ );
219
+ await epochTestSettler.start();
220
+ }
194
221
 
195
222
  if (initialAccounts.length) {
196
- const PXEConfig = { proverEnabled: aztecNodeConfig.realProofs };
197
- const wallet = await TestWallet.create(node, PXEConfig);
223
+ const wallet = await EmbeddedWallet.create(node, {
224
+ pxeConfig: { proverEnabled: aztecNodeConfig.realProofs },
225
+ ephemeral: true,
226
+ });
198
227
 
199
228
  userLog('Setting up funded test accounts...');
200
- const accountManagers = await deployFundedSchnorrAccounts(wallet, node, initialAccounts);
201
- const accountsWithSecrets = accountManagers.map((manager, i) => ({
202
- account: manager,
203
- secretKey: initialAccounts[i].secret,
204
- }));
205
- const accLogs = await createAccountLogs(accountsWithSecrets, wallet);
229
+ const accountManagers = await deployFundedSchnorrAccounts(wallet, initialAccounts);
230
+ const accLogs = await createAccountLogs(accountManagers, wallet);
206
231
  userLog(accLogs.join(''));
207
232
 
208
233
  await setupBananaFPC(initialAccounts, wallet, userLog);
@@ -216,6 +241,7 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
216
241
  const stop = async () => {
217
242
  await node.stop();
218
243
  await watcher?.stop();
244
+ await epochTestSettler?.stop();
219
245
  };
220
246
 
221
247
  return { node, stop };
@@ -227,7 +253,12 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
227
253
  */
228
254
  export async function createAztecNode(
229
255
  config: Partial<AztecNodeConfig> = {},
230
- deps: { telemetry?: TelemetryClient; blobSinkClient?: BlobSinkClientInterface; dateProvider?: DateProvider } = {},
256
+ deps: {
257
+ telemetry?: TelemetryClient;
258
+ blobClient?: BlobClientInterface;
259
+ dateProvider?: DateProvider;
260
+ proverBroker?: ProvingJobBroker;
261
+ } = {},
231
262
  options: { prefilledPublicData?: PublicDataTreeLeaf[] } = {},
232
263
  ) {
233
264
  // TODO(#12272): will clean this up. This is criminal.
@@ -237,6 +268,10 @@ export async function createAztecNode(
237
268
  ...config,
238
269
  l1Contracts: { ...l1Contracts, ...config.l1Contracts },
239
270
  };
240
- const node = await AztecNodeService.createAndSync(aztecNodeConfig, deps, options);
271
+ const node = await AztecNodeService.createAndSync(
272
+ aztecNodeConfig,
273
+ { ...deps, proverNodeDeps: { broker: deps.proverBroker } },
274
+ options,
275
+ );
241
276
  return node;
242
277
  }
@@ -1,5 +1,5 @@
1
- import type { ViemClient } from '@aztec/ethereum';
2
1
  import { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
2
+ import type { ViemClient } from '@aztec/ethereum/types';
3
3
  import { SlotNumber } from '@aztec/foundation/branded-types';
4
4
  import type { EthAddress } from '@aztec/foundation/eth-address';
5
5
  import { type Logger, createLogger } from '@aztec/foundation/log';
@@ -31,6 +31,15 @@ export class AnvilTestWatcher {
31
31
 
32
32
  private isMarkingAsProven = true;
33
33
 
34
+ // Optional callback to check if there are pending txs in the mempool.
35
+ private getPendingTxCount?: () => Promise<number>;
36
+
37
+ // Optional callback to check if the sequencer is actively building a block.
38
+ private isSequencerBuilding?: () => boolean;
39
+
40
+ // Tracks when we first observed the current unfilled slot with pending txs (real wall time).
41
+ private unfilledSlotFirstSeen?: { slot: number; realTime: number };
42
+
34
43
  constructor(
35
44
  private cheatcodes: EthCheatCodes,
36
45
  rollupAddress: EthAddress,
@@ -59,6 +68,16 @@ export class AnvilTestWatcher {
59
68
  this.isLocalNetwork = isLocalNetwork;
60
69
  }
61
70
 
71
+ /** Sets a callback to check for pending txs, used to skip unfilled slots faster when txs are waiting. */
72
+ setGetPendingTxCount(fn: () => Promise<number>) {
73
+ this.getPendingTxCount = fn;
74
+ }
75
+
76
+ /** Sets a callback to check if the sequencer is actively building, to avoid warping while it works. */
77
+ setIsSequencerBuilding(fn: () => boolean) {
78
+ this.isSequencerBuilding = fn;
79
+ }
80
+
62
81
  async start() {
63
82
  if (this.filledRunningPromise) {
64
83
  throw new Error('Watcher already watching for filled slot');
@@ -125,21 +144,14 @@ export class AnvilTestWatcher {
125
144
  async warpTimeIfNeeded() {
126
145
  try {
127
146
  const currentSlot = SlotNumber.fromBigInt(await this.rollup.read.getCurrentSlot());
128
- const pendingCheckpointNumber = BigInt(await this.rollup.read.getPendingCheckpointNumber());
147
+ const pendingCheckpointNumber = await this.rollup.read.getPendingCheckpointNumber();
129
148
  const checkpointLog = await this.rollup.read.getCheckpoint([pendingCheckpointNumber]);
130
149
  const nextSlot = SlotNumber(currentSlot + 1);
131
150
  const nextSlotTimestamp = Number(await this.rollup.read.getTimestampForSlot([BigInt(nextSlot)]));
132
151
 
133
152
  if (BigInt(currentSlot) === checkpointLog.slotNumber) {
134
- // We should jump to the next slot
135
- try {
136
- await this.cheatcodes.warp(nextSlotTimestamp, {
137
- resetBlockInterval: true,
138
- });
139
- } catch (e) {
140
- this.logger.error(`Failed to warp to timestamp ${nextSlotTimestamp}: ${e}`);
141
- }
142
-
153
+ // The current slot has been filled, we should jump to the next slot.
154
+ await this.warpToTimestamp(nextSlotTimestamp);
143
155
  this.logger.info(`Slot ${currentSlot} was filled, jumped to next slot`);
144
156
  return;
145
157
  }
@@ -149,18 +161,50 @@ export class AnvilTestWatcher {
149
161
  return;
150
162
  }
151
163
 
152
- const currentTimestamp = this.dateProvider?.now() ?? Date.now();
153
- if (currentTimestamp > nextSlotTimestamp * 1000) {
154
- try {
155
- await this.cheatcodes.warp(nextSlotTimestamp, { resetBlockInterval: true });
156
- } catch (e) {
157
- this.logger.error(`Failed to warp to timestamp ${nextSlotTimestamp}: ${e}`);
164
+ // If there are pending txs and the sequencer missed them, warp quickly (after a 2s real-time debounce) so the
165
+ // sequencer can retry in the next slot. Without this, we'd have to wait a full real-time slot duration (~36s) for
166
+ // the dateProvider to catch up to the next slot timestamp. We skip the warp if the sequencer is actively building
167
+ // to avoid invalidating its in-progress work.
168
+ if (this.getPendingTxCount) {
169
+ const pendingTxs = await this.getPendingTxCount();
170
+ if (pendingTxs > 0) {
171
+ if (this.isSequencerBuilding?.()) {
172
+ this.unfilledSlotFirstSeen = undefined;
173
+ return;
174
+ }
175
+
176
+ const realNow = Date.now();
177
+ if (!this.unfilledSlotFirstSeen || this.unfilledSlotFirstSeen.slot !== currentSlot) {
178
+ this.unfilledSlotFirstSeen = { slot: currentSlot, realTime: realNow };
179
+ return;
180
+ }
181
+
182
+ if (realNow - this.unfilledSlotFirstSeen.realTime > 2000) {
183
+ await this.warpToTimestamp(nextSlotTimestamp);
184
+ this.unfilledSlotFirstSeen = undefined;
185
+ this.logger.info(`Slot ${currentSlot} was missed with pending txs, jumped to next slot`);
186
+ }
187
+
188
+ return;
158
189
  }
190
+ }
159
191
 
192
+ // Fallback: warp when the dateProvider time has passed the next slot timestamp.
193
+ const currentTimestamp = this.dateProvider?.now() ?? Date.now();
194
+ if (currentTimestamp > nextSlotTimestamp * 1000) {
195
+ await this.warpToTimestamp(nextSlotTimestamp);
160
196
  this.logger.info(`Slot ${currentSlot} was missed, jumped to next slot`);
161
197
  }
162
198
  } catch {
163
199
  this.logger.error('mineIfSlotFilled failed');
164
200
  }
165
201
  }
202
+
203
+ private async warpToTimestamp(timestamp: number) {
204
+ try {
205
+ await this.cheatcodes.warp(timestamp, { resetBlockInterval: true });
206
+ } catch (e) {
207
+ this.logger.error(`Failed to warp to timestamp ${timestamp}: ${e}`);
208
+ }
209
+ }
166
210
  }
@@ -1,4 +1,5 @@
1
1
  import { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
2
+ import { BlockNumber } from '@aztec/foundation/branded-types';
2
3
  import { retryUntil } from '@aztec/foundation/retry';
3
4
  import type { DateProvider } from '@aztec/foundation/timer';
4
5
  import type { SequencerClient } from '@aztec/sequencer-client';
@@ -37,7 +38,7 @@ export class CheatCodes {
37
38
  * @param targetTimestamp - The target timestamp to warp to (in seconds)
38
39
  */
39
40
  async warpL2TimeAtLeastTo(sequencerClient: SequencerClient, node: AztecNode, targetTimestamp: bigint | number) {
40
- const currentL2BlockNumber = await node.getBlockNumber();
41
+ const currentL2BlockNumber: BlockNumber = await node.getBlockNumber();
41
42
 
42
43
  // We warp the L1 timestamp
43
44
  await this.eth.warp(targetTimestamp, { resetBlockInterval: true });
@@ -49,7 +50,7 @@ export class CheatCodes {
49
50
 
50
51
  await retryUntil(
51
52
  async () => {
52
- const newL2BlockNumber = await node.getBlockNumber();
53
+ const newL2BlockNumber: BlockNumber = await node.getBlockNumber();
53
54
  return newL2BlockNumber > currentL2BlockNumber;
54
55
  },
55
56
  'new block after warping L2 time',
@@ -0,0 +1,70 @@
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 { computeEpochOutHash } 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 outHash = computeEpochOutHash(messagesInEpoch);
55
+ if (!outHash.isZero()) {
56
+ await this.rollupCheatCodes.insertOutbox(epoch, outHash.toBigInt());
57
+ } else {
58
+ this.log.info(`No L2 to L1 messages in epoch ${epoch}`);
59
+ }
60
+
61
+ const lastCheckpoint = checkpointedBlocks.at(-1)?.checkpointNumber;
62
+ if (lastCheckpoint !== undefined) {
63
+ await this.rollupCheatCodes.markAsProven(lastCheckpoint);
64
+ } else {
65
+ this.log.warn(`No checkpoint found for epoch ${epoch}`);
66
+ }
67
+
68
+ return true;
69
+ }
70
+ }
@@ -1,3 +1,5 @@
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';
5
+ export { getTokenAllowedSetupFunctions } from './token_allowed_setup.js';
@@ -0,0 +1,19 @@
1
+ import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token';
2
+ import { buildAllowedElement } from '@aztec/p2p/msg_validators';
3
+ import { getContractClassFromArtifact } from '@aztec/stdlib/contract';
4
+ import type { AllowedElement } from '@aztec/stdlib/interfaces/server';
5
+
6
+ /**
7
+ * Returns Token-specific allowlist entries needed for FPC-based fee payments.
8
+ * These are test-only: FPC-based fee payment with custom tokens won't work on mainnet alpha.
9
+ */
10
+ export async function getTokenAllowedSetupFunctions(): Promise<AllowedElement[]> {
11
+ const tokenClassId = (await getContractClassFromArtifact(TokenContractArtifact)).id;
12
+ const target = { classId: tokenClassId };
13
+ return Promise.all([
14
+ // Token: needed for private transfers via FPC (transfer_to_public enqueues this)
15
+ buildAllowedElement(TokenContractArtifact, target, '_increase_public_balance', { onlySelf: true }),
16
+ // Token: needed for public transfers via FPC (fee_entrypoint_public enqueues this)
17
+ buildAllowedElement(TokenContractArtifact, target, 'transfer_in_public'),
18
+ ]);
19
+ }
@@ -1,3 +0,0 @@
1
- import type { LogFn } from '@aztec/foundation/log';
2
- export declare function startBlobSink(options: any, signalHandlers: (() => Promise<void>)[], userLog: LogFn): Promise<void>;
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnRfYmxvYl9zaW5rLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY2xpL2NtZHMvc3RhcnRfYmxvYl9zaW5rLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU9BLE9BQU8sS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBS25ELHdCQUFzQixhQUFhLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUUsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsT0FBTyxFQUFFLEtBQUssaUJBNEN4RyJ9
@@ -1 +0,0 @@
1
- {"version":3,"file":"start_blob_sink.d.ts","sourceRoot":"","sources":["../../../src/cli/cmds/start_blob_sink.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAKnD,wBAAsB,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,iBA4CxG"}
@@ -1,33 +0,0 @@
1
- import { blobSinkConfigMappings, createBlobSinkServer, getBlobSinkConfigFromEnv } from '@aztec/blob-sink/server';
2
- import { getL1Config } from '@aztec/cli/config';
3
- import { getConfigEnvVars as getTelemetryClientConfig, initTelemetryClient } from '@aztec/telemetry-client';
4
- import { extractRelevantOptions } from '../util.js';
5
- export async function startBlobSink(options, signalHandlers, userLog) {
6
- if (options.prover || options.node || options.sequencer || options.pxe || options.p2pBootstrap || options.txe) {
7
- userLog(`Starting a blob sink with --node, --sequencer, --pxe, --p2p-bootstrap, --prover or --txe is not supported.`);
8
- process.exit(1);
9
- }
10
- let blobSinkConfig = {
11
- ...getBlobSinkConfigFromEnv(),
12
- ...extractRelevantOptions(options, blobSinkConfigMappings, 'blobSink')
13
- };
14
- if (!blobSinkConfig.l1Contracts?.registryAddress || blobSinkConfig.l1Contracts.registryAddress.isZero()) {
15
- throw new Error('REGISTRY_CONTRACT_ADDRESS not set');
16
- }
17
- if (!blobSinkConfig.l1RpcUrls || blobSinkConfig.l1RpcUrls.length === 0) {
18
- throw new Error('ETHEREUM_HOSTS not set');
19
- }
20
- if (typeof blobSinkConfig.l1ChainId !== 'number') {
21
- throw new Error('L1_CHAIN_ID');
22
- }
23
- const telemetry = initTelemetryClient(getTelemetryClientConfig());
24
- const { config: chainConfig, addresses } = await getL1Config(blobSinkConfig.l1Contracts.registryAddress, blobSinkConfig.l1RpcUrls, blobSinkConfig.l1ChainId, blobSinkConfig.rollupVersion);
25
- blobSinkConfig = {
26
- ...blobSinkConfig,
27
- l1Contracts: addresses,
28
- ...chainConfig
29
- };
30
- const blobSink = await createBlobSinkServer(blobSinkConfig, telemetry);
31
- signalHandlers.push(blobSink.stop.bind(blobSink));
32
- await blobSink.start();
33
- }
@@ -1,7 +0,0 @@
1
- import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
2
- import type { LogFn } from '@aztec/foundation/log';
3
- import { type ProverNodeConfig } from '@aztec/prover-node';
4
- export declare function startProverNode(options: any, signalHandlers: (() => Promise<void>)[], services: NamespacedApiHandlers, userLog: LogFn): Promise<{
5
- config: ProverNodeConfig;
6
- }>;
7
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnRfcHJvdmVyX25vZGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGkvY21kcy9zdGFydF9wcm92ZXJfbm9kZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLQSxPQUFPLEtBQUssRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRS9FLE9BQU8sS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRW5ELE9BQU8sRUFDTCxLQUFLLGdCQUFnQixFQUl0QixNQUFNLG9CQUFvQixDQUFDO0FBUzVCLHdCQUFzQixlQUFlLENBQ25DLE9BQU8sRUFBRSxHQUFHLEVBQ1osY0FBYyxFQUFFLENBQUMsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUN2QyxRQUFRLEVBQUUscUJBQXFCLEVBQy9CLE9BQU8sRUFBRSxLQUFLLEdBQ2IsT0FBTyxDQUFDO0lBQUUsTUFBTSxFQUFFLGdCQUFnQixDQUFBO0NBQUUsQ0FBQyxDQStGdkMifQ==
@@ -1 +0,0 @@
1
- {"version":3,"file":"start_prover_node.d.ts","sourceRoot":"","sources":["../../../src/cli/cmds/start_prover_node.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE/E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EACL,KAAK,gBAAgB,EAItB,MAAM,oBAAoB,CAAC;AAS5B,wBAAsB,eAAe,CACnC,OAAO,EAAE,GAAG,EACZ,cAAc,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EACvC,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,KAAK,GACb,OAAO,CAAC;IAAE,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC,CA+FvC"}